<?xml version="1.0" encoding="utf-8"?>
<search> 
  
  
    
    <entry>
      <title>MacOS下访达目录直接跳转终端</title>
      <link href="comic/finder2iterm/"/>
      <url>comic/finder2iterm/</url>
      
        <content type="html"><![CDATA[<h1 id="iterm2的安装"><a href="#iterm2的安装" class="headerlink" title="iterm2的安装"></a>iterm2的安装</h1><p>官方地址: <a href="https://iterm2.com/">https://iterm2.com/</a></p><h1 id="脚本编辑器"><a href="#脚本编辑器" class="headerlink" title="脚本编辑器"></a>脚本编辑器</h1><p><img src= "/img/loading.gif" data-lazy-src="img.png" alt="img.png"><br>新建一个文件,粘贴下面的脚本内容<br><img src= "/img/loading.gif" data-lazy-src="img_1.png" alt="img.png"></p><h1 id="脚本"><a href="#脚本" class="headerlink" title="脚本"></a>脚本</h1><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><span class="line">(* </span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">    Open Terminal Here </span><br><span class="line">      </span><br><span class="line">    A toolbar script for Mac OS X 10.3/10.4</span><br><span class="line">      </span><br><span class="line">    Written by Brian Schlining</span><br><span class="line"> *)</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">property debug : false</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">-- when the toolbar script icon is clicked </span><br><span class="line">-- </span><br><span class="line">on run</span><br><span class="line">    tell application &quot;Finder&quot;</span><br><span class="line">        try</span><br><span class="line">            set this_folder to (the target of the front window) as alias</span><br><span class="line">        on error</span><br><span class="line">            set this_folder to startup disk</span><br><span class="line">        end try</span><br><span class="line">         </span><br><span class="line">        my process_item(this_folder)</span><br><span class="line">         </span><br><span class="line">    end tell</span><br><span class="line">end run</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">-- This handler processes folders dropped onto the toolbar script icon </span><br><span class="line">-- </span><br><span class="line">on open these_items</span><br><span class="line">    repeat with i from 1 to the count of these_items</span><br><span class="line">        set this_item to item i of these_items</span><br><span class="line">        my process_item(this_item)</span><br><span class="line">    end repeat</span><br><span class="line">end open</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">-- this subroutine processes does the actual work </span><br><span class="line">-- this version can handle this weirdo case: a folder named &quot;te&#x27;st&quot;ö te%s`t&quot;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">on process_item(this_item)</span><br><span class="line">     </span><br><span class="line">    set thePath to quoted form of POSIX path of this_item</span><br><span class="line">    set theCmd to &quot;cd &quot; &amp; thePath &amp; &quot;;clear;&quot;</span><br><span class="line">     </span><br><span class="line">    tell application &quot;iTerm&quot;</span><br><span class="line">        activate</span><br><span class="line">        -- just open a terminal and cd to thePath</span><br><span class="line">        --set newWindow to (create window with default profile)</span><br><span class="line">         </span><br><span class="line">        set aWindow to current window</span><br><span class="line">         </span><br><span class="line">        if aWindow is equal to missing value then</span><br><span class="line">            set aWindow to (create window with default profile)</span><br><span class="line">        else</span><br><span class="line">            tell aWindow</span><br><span class="line">                set t to (create tab with default profile)</span><br><span class="line">            end tell</span><br><span class="line">        end if</span><br><span class="line">         </span><br><span class="line">         </span><br><span class="line">        tell current session of aWindow</span><br><span class="line">            write text &quot;cd &quot; &amp; thePath &amp; &quot;;clear;&quot;</span><br><span class="line">        end tell</span><br><span class="line">         </span><br><span class="line">    end tell</span><br><span class="line">     </span><br><span class="line">     </span><br><span class="line">end process_item</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>保存为应用程序</p><p><img src= "/img/loading.gif" data-lazy-src="img3.png" alt="img.png"></p><p>打开刚才保存的路径,按住control+command 拖动到finder到固定位置即可</p><p><img src= "/img/loading.gif" data-lazy-src="img_2.png" alt="img.png"></p><p>当需要打开终端的时候,只需要在finder对应的文件夹中点击 刚才的图标即可!</p><p><img src= "/img/loading.gif" data-lazy-src="img_3.png" alt="img.png"></p><p>即可打开iterm,并进入对应的目录</p><p><img src= "/img/loading.gif" data-lazy-src="img_4.png" alt="img.png"></p><hr>]]></content>
      
      
      
        <tags>
            
            <tag> git </tag>
            
            <tag> linux </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Github文档索引</title>
      <link href="index/colemak/"/>
      <url>index/colemak/</url>
      
        <content type="html"><![CDATA[<blockquote><p>Created by <a href="https://www.gitbook.com/">gitbook</a></p></blockquote><ul><li><p><a href="https://blog.colemak.cn/scala/">blog.colemak.cn/scala</a></p></li><li><p><a href="https://blog.colemak.cn/jvm/">blog.colemak.cn/jvm</a></p></li><li><p><a href="https://blog.colemak.cn/springboot/">blog.colemak.cn/springboot</a></p></li><li><p><a href="https://blog.colemak.cn/springcloud/">blog.colemak.cn/springcloud</a></p></li><li><p><a href="https://blog.colemak.cn/design_pattern/">blog.colemak.cn/design_pattern</a></p></li><li><p><a href="https://blog.colemak.cn/data_algorithm/">blog.colemak.cn/data_algorithm</a></p></li></ul><ul><li><a href="https://blog.colemak.cn/elk/">blog.colemak.cn/elk</a></li><li><a href="https://blog.colemak.cn/zookeeper/">blog.colemak.cn/zookeeper</a></li><li><a href="https://blog.colemak.cn/docker/">blog.colemak.cn/docker</a></li></ul><ul><li><p><a href="https://blog.colemak.cn/vue/">blog.colemak.cn/vue</a></p></li><li><p><a href="https://blog.colemak.cn/react/">blog.colemak.cn/react</a></p></li><li><p><a href="https://blog.colemak.cn/go-camp/">blog.colemak.cn/go-camp</a></p></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> gitbook </tag>
            
            <tag> index </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Centos部署前端命令汇总</title>
      <link href="comic/centos_dev/"/>
      <url>comic/centos_dev/</url>
      
        <content type="html"><![CDATA[<h2 id="宝塔"><a href="#宝塔" class="headerlink" title="宝塔"></a>宝塔</h2><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">yum install -y wget &amp;&amp; wget -O install.sh http://download.bt.cn/install/install_6.0.sh &amp;&amp; sh install.sh</span><br><span class="line"><span class="meta">#</span><span class="bash"> ref https://www.bt.cn/bbs/thread-19376-1-1.html</span></span><br></pre></td></tr></table></figure><h3 id="卸载"><a href="#卸载" class="headerlink" title="卸载"></a>卸载</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wget http://download.bt.cn/install/bt-uninstall.sh</span><br><span class="line">sh bt-uninstall.sh</span><br></pre></td></tr></table></figure><h2 id="git"><a href="#git" class="headerlink" title="git"></a>git</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y git</span><br></pre></td></tr></table></figure><h2 id="创建用户"><a href="#创建用户" class="headerlink" title="创建用户"></a>创建用户</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">adduser work</span><br><span class="line"><span class="meta">#</span><span class="bash"> 设置密码</span></span><br><span class="line">passwd work</span><br><span class="line"><span class="meta">#</span><span class="bash"> ref : https://blog.csdn.net/nieji3057/article/details/79421874</span></span><br></pre></td></tr></table></figure><h2 id="nodejs"><a href="#nodejs" class="headerlink" title="nodejs"></a>nodejs</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">repo: https:&#x2F;&#x2F;nodejs.org&#x2F;dist&#x2F;latest-v16.x&#x2F;</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -xzvf node-v16.13.0-xxx</span><br></pre></td></tr></table></figure><p>2、通过ftp工具上传到linux服务，解压安装包</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -xvf node-v10.16.0-linux-x64.tar.xz</span><br></pre></td></tr></table></figure><p>3、移动并改名文件夹（不改名也行）</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd &#x2F;usr&#x2F;local&#x2F;</span><br><span class="line">mv &#x2F;var&#x2F;ftp&#x2F;pub&#x2F;node-v10.16.0-linux-64 . &#x2F;&#x2F;后面的.表示移动到当前目录</span><br><span class="line">mv node-v10.16.0.0-linux-64&#x2F; nodejs</span><br></pre></td></tr></table></figure><p>4、让npm和node命令全局生效</p><p>方式一：环境变量方式（这种方式似乎只对登录用户有效？）</p><p>1）、加入环境变量，在 /etc/profile 文件末尾增加配置</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vi &#x2F;etc&#x2F;profileexport PATH&#x3D;$PATH:&#x2F;usr&#x2F;local&#x2F;nodejs&#x2F;bin</span><br></pre></td></tr></table></figure><p>2）、执行命令使配置文件生效</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source &#x2F;etc&#x2F;profile</span><br></pre></td></tr></table></figure><p>方式二：软链接方式（推荐）</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ln -s &#x2F;usr&#x2F;local&#x2F;nodejs&#x2F;bin&#x2F;npm &#x2F;usr&#x2F;local&#x2F;bin&#x2F;</span><br><span class="line">ln -s &#x2F;usr&#x2F;local&#x2F;nodejs&#x2F;bin&#x2F;node &#x2F;usr&#x2F;local&#x2F;bin&#x2F;</span><br></pre></td></tr></table></figure><p>5、查看nodejs是否安装成功</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node -vnpm -v</span><br></pre></td></tr></table></figure><blockquote><p>ref : <a href="https://www.cnblogs.com/zhi-leaf/p/10979629.html">https://www.cnblogs.com/zhi-leaf/p/10979629.html</a></p></blockquote><h2 id="nvm"><a href="#nvm" class="headerlink" title="nvm"></a>nvm</h2><h3 id="安装Node-js版本管理工具nvm"><a href="#安装Node-js版本管理工具nvm" class="headerlink" title="安装Node.js版本管理工具nvm"></a>安装Node.js版本管理工具nvm</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -o- https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;creationix&#x2F;nvm&#x2F;v0.33.11&#x2F;install.sh | bash</span><br></pre></td></tr></table></figure><p>或者</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget -qO- https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;creationix&#x2F;nvm&#x2F;v0.33.11&#x2F;install.sh | bash</span><br></pre></td></tr></table></figure><p>还可以用下面这种方法</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone git:&#x2F;&#x2F;github.com&#x2F;creationix&#x2F;nvm.git ~&#x2F;nvm</span><br></pre></td></tr></table></figure><h3 id="验证安装"><a href="#验证安装" class="headerlink" title="验证安装"></a>验证安装</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">command -v nvm</span><br></pre></td></tr></table></figure><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><p>设置nvm自动运行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">echo &quot;source ~&#x2F;nvm&#x2F;nvm.sh&quot; &gt;&gt; ~&#x2F;.bashrc</span><br><span class="line">source ~&#x2F;.bashrc</span><br></pre></td></tr></table></figure><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><p>查询Node.js版本</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nvm list-remote</span><br></pre></td></tr></table></figure><p>安装Node.js版本</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nvm install v16.11.1</span><br></pre></td></tr></table></figure><p>切换Node.js版本</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nvm use v7.6.0</span><br></pre></td></tr></table></figure><p>升级npm</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm -g install npm@5.7.1</span><br></pre></td></tr></table></figure><blockquote><p>ref : <a href="https://www.cnblogs.com/ycyzharry/p/10186251.html">https://www.cnblogs.com/ycyzharry/p/10186251.html</a></p></blockquote><h3 id="换源"><a href="#换源" class="headerlink" title="换源"></a>换源</h3><p>当前nvm在github上的最新版本是0.33.8，首先运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -o- https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;creationix&#x2F;nvm&#x2F;v0.33.8&#x2F;install.sh | bash</span><br></pre></td></tr></table></figure><p>待到安装完成提示用户设置环境变量的时候，修改<code>.bash_profile</code>，在末尾加入：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">echo &quot;export NVM_NODEJS_ORG_MIRROR=http://npm.taobao.org/mirrors/node&quot; &gt;&gt; ~/.bash_profile</span><br><span class="line">echo &quot;export NVM_DIR=\&quot;$HOME/.nvm\&quot;&quot; &gt;&gt; ~/.bash_profile</span><br><span class="line">echo &quot;[ -s \&quot;$NVM_DIR/nvm.sh\&quot; ] &amp;&amp; \. \&quot;$NVM_DIR/nvm.sh\&quot;&quot; &gt;&gt; ~/.bash_profile</span><br><span class="line">echo &quot;[ -s \&quot;$NVM_DIR/bash_completion\&quot; ] &amp;&amp; \. \&quot;$NVM_DIR/bash_completion\&quot;&quot; &gt;&gt; ~/.bash_profile</span><br></pre></td></tr></table></figure><p>随后使配置生效，运行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd ~</span><br><span class="line">source .bash_profile</span><br></pre></td></tr></table></figure><p>当前，使配置生效的方法还有直接退出终端，新开一个终端的方法。<br>运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">nvm ls</span><br><span class="line">nvm ls-remote</span><br></pre></td></tr></table></figure><p>就可以分别查看本地已经安装的版</p><blockquote><p>ref : <a href="https://blog.csdn.net/caoshiying/article/details/79580261">https://blog.csdn.net/caoshiying/article/details/79580261</a></p></blockquote><h3 id="npm换源"><a href="#npm换源" class="headerlink" title="npm换源"></a>npm换源</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config set registry https:&#x2F;&#x2F;registry.npm.taobao.org</span><br></pre></td></tr></table></figure><p>// 配置后可通过下面方式来验证是否成功<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm config get registry</span><br><span class="line"> </span><br><span class="line">&#x2F;&#x2F; 或npm info express</span><br></pre></td></tr></table></figure></p><blockquote><p>ref: <a href="https://www.jianshu.com/p/0deb70e6f395">https://www.jianshu.com/p/0deb70e6f395</a></p></blockquote><h2 id="ssh"><a href="#ssh" class="headerlink" title="ssh"></a>ssh</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">cd ~</span><br><span class="line">ll -a</span><br><span class="line">cd /home/work</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 测试一下</span></span><br><span class="line">ping 49.233.107.254</span><br><span class="line">scp -r -v /home/work/a play@49.223.107.254:/home/play/</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 实际的</span></span><br><span class="line">scp -r /home/work/.ssh play@49.223.107.254:/home/play/</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="改-ssh权限"><a href="#改-ssh权限" class="headerlink" title="改.ssh权限"></a>改.ssh权限</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cd ~</span><br><span class="line"><span class="meta">#</span><span class="bash"> 查看</span></span><br><span class="line">ll -a</span><br><span class="line"><span class="meta">#</span><span class="bash"> 改权限</span></span><br><span class="line">chmod 600  /home/play/.ssh/*</span><br></pre></td></tr></table></figure><h2 id="拉代码"><a href="#拉代码" class="headerlink" title="拉代码"></a>拉代码</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone git@github.com:moderateReact/moderate-react-template.git</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> git </tag>
            
            <tag> linux </tag>
            
            <tag> system </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>deepin系统开机自动切换colemak键盘布局</title>
      <link href="linux/deepin-colemak/"/>
      <url>linux/deepin-colemak/</url>
      
        <content type="html"><![CDATA[<h2 id="1-xmodmap文件准备"><a href="#1-xmodmap文件准备" class="headerlink" title="1. xmodmap文件准备"></a>1. xmodmap文件准备</h2><p>可以参考</p><p><a href="https://wiki.archlinux.org/title/Xmodmap_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)">https://wiki.archlinux.org/title/Xmodmap_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)</a></p><p>我们需要一个colemak的映射文件,命名为<code>.Xmodmap</code></p><p>即 创建一个键映射表（即文件 <code>~/.Xmodmap</code>）： </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xmodmap -pke &gt; ~/.Xmodmap</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="1633613241160.png" alt="1633613241160"></p><p>修改文件内容如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line">clear lock</span><br><span class="line"></span><br><span class="line">keycode  10 = 1 exclam 1 exclam</span><br><span class="line">keycode  11 = 2 at 2 at</span><br><span class="line">keycode  12 = 3 numbersign 3 numbersign</span><br><span class="line">keycode  13 = 4 dollar 4 dollar</span><br><span class="line">keycode  14 = 5 percent 5 percent</span><br><span class="line">keycode  15 = 6 asciicircum 6 asciicircum</span><br><span class="line">keycode  16 = 7 ampersand 7 ampersand</span><br><span class="line">keycode  17 = 8 asterisk 8 asterisk</span><br><span class="line">keycode  18 = 9 parenleft 9 parenleft</span><br><span class="line">keycode  19 = 0 parenright 0 parenright</span><br><span class="line">keycode  20 = minus underscore minus underscore</span><br><span class="line">keycode  21 = equal plus equal plus</span><br><span class="line">keycode  22 = BackSpace BackSpace BackSpace BackSpace</span><br><span class="line">keycode  23 = Tab ISO_Left_Tab Tab ISO_Left_Tab</span><br><span class="line">keycode  24 = q Q q Q</span><br><span class="line">keycode  25 = w W w W</span><br><span class="line">keycode  26 = f F f F</span><br><span class="line">keycode  27 = p P p P</span><br><span class="line">keycode  28 = g G g G</span><br><span class="line">keycode  29 = j J j J</span><br><span class="line">keycode  30 = l L l L</span><br><span class="line">keycode  31 = u U u U</span><br><span class="line">keycode  32 = y Y y Y</span><br><span class="line">keycode  33 = semicolon colon semicolon colon</span><br><span class="line">keycode  34 = bracketleft braceleft bracketleft braceleft</span><br><span class="line">keycode  35 = bracketright braceright bracketright braceright</span><br><span class="line">keycode  36 = Return NoSymbol Return</span><br><span class="line">keycode  37 = Control_L NoSymbol Control_L</span><br><span class="line">keycode  38 = a A a A</span><br><span class="line">keycode  39 = r R r R</span><br><span class="line">keycode  40 = s S s S</span><br><span class="line">keycode  41 = t T t T</span><br><span class="line">keycode  42 = d D d D</span><br><span class="line">keycode  43 = h H h H</span><br><span class="line">keycode  44 = n N n N</span><br><span class="line">keycode  45 = e E e E</span><br><span class="line">keycode  46 = i I i I</span><br><span class="line">keycode  47 = o O o O</span><br><span class="line">keycode  48 = apostrophe quotedbl apostrophe quotedbl</span><br><span class="line">keycode  49 = grave asciitilde grave asciitilde</span><br><span class="line">keycode  50 = Shift_L NoSymbol Shift_L</span><br><span class="line">keycode  51 = backslash bar backslash bar</span><br><span class="line">keycode  52 = z Z z Z</span><br><span class="line">keycode  53 = x X x X</span><br><span class="line">keycode  54 = c C c C</span><br><span class="line">keycode  55 = v V v V</span><br><span class="line">keycode  56 = b B b B</span><br><span class="line">keycode  57 = k K k K</span><br><span class="line">keycode  58 = m M m M</span><br><span class="line">keycode  59 = comma less comma less</span><br><span class="line">keycode  60 = period greater period greater</span><br><span class="line">keycode  61 = slash question slash question</span><br><span class="line">keycode  62 = Shift_R NoSymbol Shift_R</span><br><span class="line">keycode  64 = Alt_L Meta_L Alt_L Meta_L</span><br><span class="line">keycode  65 = space NoSymbol space</span><br><span class="line">keycode  66 = BackSpace BackSpace Delete Delete</span><br><span class="line">keycode 105 = Control_R NoSymbol Control_R</span><br><span class="line">keycode 108 = Mode_switch NoSymbol Mode_switch</span><br><span class="line">keycode 133 = Super_L NoSymbol Super_L</span><br><span class="line">keycode 134 = Super_R NoSymbol Super_R</span><br><span class="line">keycode 135 = Menu NoSymbol Menu</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="2-测试是否生效"><a href="#2-测试是否生效" class="headerlink" title="2. 测试是否生效"></a>2. 测试是否生效</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xmodmap ~/.Xmodmap</span><br></pre></td></tr></table></figure><h2 id="3-配置开机启动"><a href="#3-配置开机启动" class="headerlink" title="3. 配置开机启动"></a>3. 配置开机启动</h2><blockquote><p>首先 需要 准备一个启动脚本</p></blockquote><p>比如创建一个名为<code>colemak.sh</code>的文件</p><p>内容如下</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xmodmap ~/.Xmodmap</span><br></pre></td></tr></table></figure><p>将脚本文件粘贴到 <code>~/.config/autostart</code>目录下面</p><p>生成启动快捷方式,也粘贴到 <code>~/.config/autostart</code>目录下面</p><p>及<code>colemak.desktop</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[Desktop Entry]</span><br><span class="line"></span><br><span class="line">Type=Application</span><br><span class="line"></span><br><span class="line">Exec=/home/victor/.config/autostart/colemak.sh</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="1633613256359.png" alt="1633613256359"></p><p>重新启动即可</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reboot</span><br></pre></td></tr></table></figure><h1 id="参考"><a href="#参考" class="headerlink" title="参考:"></a>参考:</h1><h2 id="上个版本参考"><a href="#上个版本参考" class="headerlink" title="上个版本参考"></a>上个版本参考</h2><p><a href="https://blog.csdn.net/BenSYZ/article/details/104520678">https://blog.csdn.net/BenSYZ/article/details/104520678</a></p><p><a href="http://www.voidcn.com/article/p-bplopzoo-bwq.html">http://www.voidcn.com/article/p-bplopzoo-bwq.html</a></p><p><a href="https://baijiahao.baidu.com/s?id=1666002986214880905&amp;wfr=spider&amp;for=pc">https://baijiahao.baidu.com/s?id=1666002986214880905&amp;wfr=spider&amp;for=pc</a></p><h2 id="xmodmap参考"><a href="#xmodmap参考" class="headerlink" title="xmodmap参考:"></a>xmodmap参考:</h2><p><a href="https://wiki.archlinux.org/title/Xmodmap_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)">https://wiki.archlinux.org/title/Xmodmap_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)</a></p><p>colemak替换文件来自: </p><p><a href="https://download.csdn.net/download/weixin_42176827/19824153">https://download.csdn.net/download/weixin_42176827/19824153</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> colemak </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>RabbitMQ面试题</title>
      <link href="middleware/mq/rabbitmq/"/>
      <url>middleware/mq/rabbitmq/</url>
      
        <content type="html"><![CDATA[<h2 id="RabbitMQ是什么？"><a href="#RabbitMQ是什么？" class="headerlink" title="RabbitMQ是什么？" data-pjax-state=""></a>RabbitMQ 是什么？</h2><p>RabbitMQ 是实现了高级消息队列协议（<code>AMQP</code>）的开源消息代理软件（亦称面向消息的中间件）。RabbitMQ 服务器是用 Erlang 语言编写的，而群集和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。</p><p>PS: 也可能直接问什么是消息队列？消息队列就是一个使用队列来通信的组件。</p><h2 id="RabbitMQ特点"><a href="#RabbitMQ特点" class="headerlink" title="RabbitMQ特点?" data-pjax-state=""></a>RabbitMQ 特点？</h2><p><strong>可靠性</strong>: RabbitMQ 使用一些机制来保证可靠性， 如持久化、传输确认及发布确认等。</p><p><strong>灵活的路由</strong> : 在消息进入队列之前，通过交换器来路由消息。对于典型的路由功能， RabbitMQ 己经提供了一些内置的交换器来实现。针对更复杂的路由功能，可以将多个 交换器绑定在一起， 也可以通过插件机制来实现自己的交换器。</p><p><strong>扩展性</strong>: 多个 RabbitMQ 节点可以组成一个集群，也可以根据实际业务情况动态地扩展 集群中节点。</p><p><strong>高可用性</strong> : 队列可以在集群中的机器上设置镜像，使得在部分节点出现问题的情况下队 列仍然可用。</p><p><strong>多种协议</strong>: RabbitMQ 除了原生支持 AMQP 协议，还支持 STOMP， MQTT 等多种消息 中间件协议。</p><p><strong>多语言客户端</strong> :RabbitMQ 几乎支持所有常用语言，比如 Java、 Python、 Ruby、 PHP、 C#、 JavaScript 等。</p><p><strong>管理界面</strong> : RabbitMQ 提供了一个易用的用户界面，使得用户可以监控和管理消息、集 群中的节点等。</p><p><strong>插件机制</strong> : RabbitMQ 提供了许多插件 ， 以实现从多方面进行扩展，当然也可以编写自 己的插件。</p><h2 id="AMQP是什么"><a href="#AMQP是什么" class="headerlink" title="AMQP是什么?" data-pjax-state=""></a>AMQP 是什么？</h2><p>RabbitMQ 就是 AMQP 协议的 <code>Erlang</code> 的实现 (当然 RabbitMQ 还支持 <code>STOMP2</code>、 <code>MQTT3</code> 等协议 ) AMQP 的模型架构 和 RabbitMQ 的模型架构是一样的，生产者将消息发送给交换器，交换器和队列绑定 。</p><p>RabbitMQ 中的交换器、交换器类型、队列、绑定、路由键等都是遵循的 AMQP 协议中相 应的概念。目前 RabbitMQ 最新版本默认支持的是 AMQP 0-9-1。</p><h2 id="AMQP协议3层？"><a href="#AMQP协议3层？" class="headerlink" title="AMQP协议3层？" data-pjax-state=""></a>AMQP 协议 3 层？</h2><p><strong>Module Layer</strong>: 协议最高层，主要定义了一些客户端调用的命令，客户端可以用这些命令实现自己的业务逻辑。</p><p><strong>Session Layer</strong>: 中间层，主要负责客户端命令发送给服务器，再将服务端应答返回客户端，提供可靠性同步机制和错误处理。</p><p><strong>TransportLayer</strong>: 最底层，主要传输二进制数据流，提供帧的处理、信道服用、错误检测和数据表示等。</p><h2 id="AMQP模型的几大组件？"><a href="#AMQP模型的几大组件？" class="headerlink" title="AMQP模型的几大组件？" data-pjax-state=""></a>AMQP 模型的几大组件？</h2>交换器 (Exchange)：消息代理服务器中用于把消息路由到队列的组件。队列 (Queue)：用来存储消息的数据结构，位于硬盘或内存中。绑定 (Binding)：一套规则，告知交换器消息应该将消息投递给哪个队列。<h2 id="说说生产者Producer和消费者Consumer"><a href="#说说生产者Producer和消费者Consumer" class="headerlink" title="说说生产者Producer和消费者Consumer?" data-pjax-state=""></a>说说生产者 Producer 和消费者 Consumer?</h2><p>生产者</p><p>消息生产者，就是投递消息的一方。<br>消息一般包含两个部分：消息体（<code>payload</code>) 和标签 (<code>Label</code>)。</p><p>消费者</p><p>消费消息，也就是接收消息的一方。<br>消费者连接到 RabbitMQ 服务器，并订阅到队列上。消费消息时只消费消息体，丢弃标签。</p><h2 id="为什么需要消息队列？"><a href="#为什么需要消息队列？" class="headerlink" title="为什么需要消息队列？" data-pjax-state=""></a>为什么需要消息队列？</h2><p>从本质上来说是因为互联网的快速发展，业务不断扩张，促使技术架构需要不断的演进。</p><p>从以前的单体架构到现在的微服务架构，成百上千的服务之间相互调用和依赖。从互联网初期一个服务器上有 100 个在线用户已经很了不得，到现在坐拥 10 亿日活的微信。此时，我们需要有一个「工具」来解耦服务之间的关系、控制资源合理合时的使用以及缓冲流量洪峰等等。因此，消息队列就应运而生了。</p><p>它常用来实现：<code>异步处理</code>、<code>服务解耦</code>、<code>流量控制（削峰）</code>。</p><h2 id="说说Broker服务节点、Queue队列、Exchange交换器？"><a href="#说说Broker服务节点、Queue队列、Exchange交换器？" class="headerlink" title="说说Broker服务节点、Queue队列、Exchange交换器？" data-pjax-state=""></a>说说 Broker 服务节点、Queue 队列、Exchange 交换器？</h2>Broker 可以看做 RabbitMQ 的服务节点。一般请下一个 Broker 可以看做一个 RabbitMQ 服务器。Queue:RabbitMQ 的内部对象，用于存储消息。多个消费者可以订阅同一队列，这时队列中的消息会被平摊（轮询）给多个消费者进行处理。Exchange: 生产者将消息发送到交换器，由交换器将消息路由到一个或者多个队列中。当路由不到时，或返回给生产者或直接丢弃。<h2 id="消息队列有什么优缺点"><a href="#消息队列有什么优缺点" class="headerlink" title="消息队列有什么优缺点" data-pjax-state=""></a>消息队列有什么优缺点</h2><p>优点上面已经说了，就是在特殊场景下有其对应的好处，解耦、异步、削峰。缺点有以下几个：</p><p>系统可用性降低 系统引入的外部依赖越多，越容易挂掉。万一 MQ 挂了，MQ 一挂，整套系统崩 溃，你不就完了？<br>系统复杂度提高 硬生生加个 MQ 进来，你怎么保证消息没有重复消费？怎么处理消息丢失的情况？<br>怎么保证消息传递的顺序性？问题一大堆。<br>一致性问题 A 系统处理完了直接返回成功了，人都以为你这个请求就成功了；但是问题是，要是 BCD 三个系统那里，BD 两个系统写库成功了，结果 C 系统写库失败了，咋整？你这数据就不一致 了。</p><h2 id="如何保证消息的可靠性？"><a href="#如何保证消息的可靠性？" class="headerlink" title="如何保证消息的可靠性？" data-pjax-state=""></a>如何保证消息的可靠性？</h2><p>消息到 MQ 的过程中搞丢，MQ 自己搞丢，MQ 到消费过程中搞丢。</p><p><code>生产者到RabbitMQ</code>：事务机制和 Confirm 机制，注意：事务机制和 Confirm 机制是互斥的，两者不能共存，会导致 RabbitMQ 报错。</p><p><code>RabbitMQ自身</code>：持久化、集群、普通模式、镜像模式。</p><p><code>RabbitMQ到消费者</code>：basicAck 机制、死信队列、消息补偿机制。</p><h2 id="什么是RoutingKey路由键？"><a href="#什么是RoutingKey路由键？" class="headerlink" title="什么是RoutingKey路由键？" data-pjax-state=""></a>什么是 RoutingKey 路由键？</h2><p>生产者将消息发送给交换器的时候，会指定一个 <code>RoutingKey</code>, 用来指定这个消息的路由规则，这个 <code>RoutingKey</code> 需要与交换器类型和绑定键 (<code>BindingKey</code>) 联合使用才能最终生效。</p><h2 id="Binding绑定？"><a href="#Binding绑定？" class="headerlink" title="Binding绑定？" data-pjax-state=""></a>Binding 绑定？</h2><p>通过绑定将交换器和队列关联起来，一般会指定一个 <code>BindingKey</code>, 这样 RabbitMq 就知道如何正确路由消息到队列了。</p><h2 id="交换器4种类型？"><a href="#交换器4种类型？" class="headerlink" title="交换器4种类型？" data-pjax-state=""></a>交换器 4 种类型？</h2><p>主要有以下 4 种。</p><p>fanout: 把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中。<br>direct: 把消息路由到 BindingKey 和 RoutingKey 完全匹配的队列中。<br>topic:<br> 匹配规则：</p><figure class="highlight plain"><div class="highlight-tools "><i class="fas fa-angle-down expand "></i><div class="code-lang">Code</div><div class="copy-notice"></div><i class="fas fa-paste copy-button"></i></div><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">RoutingKey` 为一个 点号'.': 分隔的字符串。比如: `java.xiaoka.show</span><br></pre></td></tr></tbody></table></figure><p><code>BindingKey</code> 和 <code>RoutingKey</code> 一样也是点号 “.“分隔的字符串。</p><p><code>BindingKey</code> 可使用 * 和 # 用于做模糊匹配，* 匹配一个单词，# 匹配多个或者 0 个</p><p><code>headers</code>: 不依赖路由键匹配规则路由消息。是根据发送消息内容中的 <code>headers</code> 属性进行匹配。性能差，基本用不到。</p><h2 id="生产者消息运转？"><a href="#生产者消息运转？" class="headerlink" title="生产者消息运转？" data-pjax-state=""></a>生产者消息运转？</h2><p><code>Producer</code> 先连接到 Broker, 建立连接 Connection, 开启一个信道 (Channel)。</p><p><code>Producer</code> 声明一个交换器并设置好相关属性。</p><p><code>Producer</code> 声明一个队列并设置好相关属性。</p><p><code>Producer</code> 通过路由键将交换器和队列绑定起来。</p><p><code>Producer</code> 发送消息到 <code>Broker</code>, 其中包含路由键、交换器等信息。</p><p>相应的交换器根据接收到的路由键查找匹配的队列。</p><p>如果找到，将消息存入对应的队列，如果没有找到，会根据生产者的配置丢弃或者退回给生产者。</p><p>关闭信道。</p><p>管理连接。</p><h2 id="消费者接收消息过程？"><a href="#消费者接收消息过程？" class="headerlink" title="消费者接收消息过程？" data-pjax-state=""></a>消费者接收消息过程？</h2><p><code>Producer</code> 先连接到 <code>Broker</code>, 建立连接 <code>Connection</code>, 开启一个信道 (<code>Channel</code>)。</p><p>向 <code>Broker</code> 请求消费响应的队列中消息，可能会设置响应的回调函数。</p><p>等待 <code>Broker</code> 回应并投递相应队列中的消息，接收消息。</p><p>消费者确认收到的消息，<code>ack</code>。</p><p><code>RabbitMq</code> 从队列中删除已经确定的消息。</p><p>关闭信道。</p><p>关闭连接。</p><h3 id="交换器无法根据自身类型和路由键找到符合条件队列时，有哪些处理？"><a href="#交换器无法根据自身类型和路由键找到符合条件队列时，有哪些处理？" class="headerlink" title="交换器无法根据自身类型和路由键找到符合条件队列时，有哪些处理？" data-pjax-state=""></a>交换器无法根据自身类型和路由键找到符合条件队列时，有哪些处理？</h3>mandatory ：true 返回消息给生产者。mandatory: false 直接丢弃。<h2 id="死信队列？"><a href="#死信队列？" class="headerlink" title="死信队列？" data-pjax-state=""></a>死信队列？</h2><p>DLX，全称为 <code>Dead-Letter-Exchange</code>，死信交换器，死信邮箱。当消息在一个队列中变成死信 (<code>dead message</code>) 之后，它能被重新被发送到另一个交换器中，这个交换器就是 DLX，绑定 DLX 的队列就称之为死信队列。</p><h2 id="导致的死信的几种原因？"><a href="#导致的死信的几种原因？" class="headerlink" title="导致的死信的几种原因？" data-pjax-state=""></a>导致的死信的几种原因？</h2>消息被拒（<code>Basic.Reject /Basic.Nack</code>) 且 <code>requeue = false</code>。消息 TTL 过期。队列满了，无法再添加。<h2 id="延迟队列？"><a href="#延迟队列？" class="headerlink" title="延迟队列？" data-pjax-state=""></a>延迟队列？</h2><p>存储对应的延迟消息，指当消息被发送以后，并不想让消费者立刻拿到消息，而是等待特定时间后，消费者才能拿到这个消息进行消费。</p><h2 id="优先级队列？"><a href="#优先级队列？" class="headerlink" title="优先级队列？" data-pjax-state=""></a>优先级队列？</h2>优先级高的队列会先被消费。可以通过 <code>x-max-priority</code> 参数来实现。当消费速度大于生产速度且 Broker 没有堆积的情况下，优先级显得没有意义。<h2 id="事务机制？"><a href="#事务机制？" class="headerlink" title="事务机制？" data-pjax-state=""></a>事务机制？</h2><p>RabbitMQ 客户端中与事务机制相关的方法有三个:</p><p><code>channel.txSelect</code> 用于将当前的信道设置成事务模式。</p><p><code>channel . txCommit</code> 用于提交事务 。</p><p><code>channel . txRollback</code> 用于事务回滚，如果在事务提交执行之前由于 RabbitMQ 异常崩溃或者其他原因抛出异常，通过 txRollback 来回滚。</p><h2 id="发送确认机制？"><a href="#发送确认机制？" class="headerlink" title="发送确认机制？" data-pjax-state=""></a>发送确认机制？</h2><p>生产者把信道设置为 <code>confirm</code> 确认模式，设置后，所有再改信道发布的消息都会被指定一个唯一的 ID，一旦消息被投递到所有匹配的队列之后，RabbitMQ 就会发送一个确认（<code>Basic.Ack</code>) 给生产者（包含消息的唯一 ID)，这样生产者就知道消息到达对应的目的地了。</p><h2 id="消费者获取消息的方式？"><a href="#消费者获取消息的方式？" class="headerlink" title="消费者获取消息的方式？" data-pjax-state=""></a>消费者获取消息的方式？</h2>推拉<h2 id="消费者某些原因无法处理当前接受的消息如何来拒绝？"><a href="#消费者某些原因无法处理当前接受的消息如何来拒绝？" class="headerlink" title="消费者某些原因无法处理当前接受的消息如何来拒绝？" data-pjax-state=""></a>消费者某些原因无法处理当前接受的消息如何来拒绝？</h2><p>channel .basicNack channel .basicReject</p><h2 id="消息传输保证层级？"><a href="#消息传输保证层级？" class="headerlink" title="消息传输保证层级？" data-pjax-state=""></a>消息传输保证层级？</h2><p><code>At most once</code>: 最多一次。消息可能会丢失，但不会重复传输。</p><p><code>At least once</code>：最少一次。消息绝不会丢失，但可能会重复传输。</p><p><code>Exactly once</code>:  恰好一次，每条消息肯定仅传输一次。</p><h2 id="了解Virtual-Host吗"><a href="#了解Virtual-Host吗" class="headerlink" title="了解Virtual Host吗?" data-pjax-state=""></a>了解 Virtual Host 吗？</h2><p>每一个 RabbitMQ 服务器都能创建虚拟的消息服务器，也叫虚拟主机 (virtual host)，简称 vhost。默认为 “/”。</p><h2 id="集群中的节点类型？"><a href="#集群中的节点类型？" class="headerlink" title="集群中的节点类型？" data-pjax-state=""></a>集群中的节点类型？</h2><p>内存节点：ram, 将变更写入内存。</p><p>磁盘节点：disc, 磁盘写入操作。</p><p>RabbitMQ 要求最少有一个磁盘节点。</p><h2 id="队列结构？"><a href="#队列结构？" class="headerlink" title="队列结构？" data-pjax-state=""></a>队列结构？</h2><p>通常由以下两部分组成？</p><p><code>rabbit_amqqueue_process</code>: 负责协议相关的消息处理，即接收生产者发布的消息、向消费者交付消息、处理消息的确认 (包括生产端的 confirm 和消费端的 ack) 等。</p><p><code>backing_queue</code>: 是消息存储的具体形式和引擎，并向 rabbit a<code>mqqueue process</code> 提供相关的接口以供调用。</p><h2 id="RabbitMQ中消息可能有的几种状态"><a href="#RabbitMQ中消息可能有的几种状态" class="headerlink" title="RabbitMQ中消息可能有的几种状态?" data-pjax-state=""></a>RabbitMQ 中消息可能有的几种状态？</h2><p><code>alpha</code>: 消息内容 (包括消息体、属性和 headers) 和消息索引都存储在内存中 。</p><p><code>beta</code>: 消息内容保存在磁盘中，消息索引保存在内存中。</p><p><code>gamma</code>: 消息内容保存在磁盘中，消息索引在磁盘和内存中都有 。</p><p><code>delta</code>: 消息内容和索引都在磁盘中 。</p><h2 id="在何种场景下使用了消息中间件？"><a href="#在何种场景下使用了消息中间件？" class="headerlink" title="在何种场景下使用了消息中间件？" data-pjax-state=""></a>在何种场景下使用了消息中间件？</h2>接口之间耦合比较严重面对大流量并发时，容易被冲垮存在性能问题<h2 id="生产者如何将消息可靠投递到MQ？"><a href="#生产者如何将消息可靠投递到MQ？" class="headerlink" title="生产者如何将消息可靠投递到MQ？" data-pjax-state=""></a>生产者如何将消息可靠投递到 MQ？</h2><p>Client 发送消息给 MQ；</p><p>MQ 将消息持久化后，发送 Ack 消息给 Client，此处有可能因为网络问题导致 Ack 消息无法发送到 Client，那么 Client 在等待超时后，会重传消息；</p><p>Client 收到 Ack 消息后，认为消息已经投递成功。</p><h2 id="MQ如何将消息可靠投递到消费者？"><a href="#MQ如何将消息可靠投递到消费者？" class="headerlink" title="MQ如何将消息可靠投递到消费者？" data-pjax-state=""></a>MQ 如何将消息可靠投递到消费者？</h2><p>MQ 将消息 push 给 Client（或 Client 来 pull 消息）</p><p>Client 得到消息并做完业务逻辑</p><p>Client 发送 Ack 消息给 MQ，通知 MQ 删除该消息，此处有可能因为网络问题导致 Ack 失败，那么 Client 会重复消息，这里就引出消费幂等的问题；</p><p>MQ 将已消费的消息删除</p><h2 id="如何保证RabbitMQ消息队列的高可用"><a href="#如何保证RabbitMQ消息队列的高可用" class="headerlink" title="如何保证RabbitMQ消息队列的高可用?" data-pjax-state=""></a>如何保证 RabbitMQ 消息队列的高可用？</h2><p>RabbitMQ 有三种模式：<code>单机模式</code>，<code>普通集群模式</code>，<code>镜像集群模式</code>。</p><p><strong>单机模式</strong>：就是 demo 级别的，一般就是你本地启动了玩玩儿的，没人生产用单机模式。</p><p><strong>普通集群模式</strong>：意思就是在多台机器上启动多个 RabbitMQ 实例，每个机器启动一个。</p><p><strong>镜像集群模式</strong>：这种模式，才是所谓的 RabbitMQ 的高可用模式，跟普通集群模式不一样的是，你创建的 queue，无论元数据 (元数据指 RabbitMQ 的配置数据) 还是 queue 里的消息都会存在于多个实例上，然后每次你写消息到 queue 的时候，都会自动把消息到多个实例的 queue 里进行消息同步。</p><h1 id="原文链接"><a href="#原文链接" class="headerlink" title="原文链接:"></a>原文链接:</h1><p><a href="https://zhangc233.github.io/2021/07/30/RabbitMQ%E9%9D%A2%E8%AF%95%E9%A2%98/#%E9%98%9F%E5%88%97%E7%BB%93%E6%9E%84%EF%BC%9F">zhangc233</a></p><h1 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h1><p><a href="https://victorfengming.gitee.io/file/pdf/rabbitmq/sgg_rabbitmq.pdf">sgg_rabbitmq</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>在自己的服务器上搭建git服务</title>
      <link href="comic/git-server/"/>
      <url>comic/git-server/</url>
      
        <content type="html"><![CDATA[<h1 id="Git-服务器搭建"><a href="#Git-服务器搭建" class="headerlink" title="Git 服务器搭建"></a>Git 服务器搭建</h1><p>上一章节中我们远程仓库使用了 Github，Github 公开的项目是免费的，2019 年开始 Github 私有存储库也可以无限制使用。</p><p>这当然我们也可以自己搭建一台 Git 服务器作为私有仓库使用。</p><p>接下来我们将以 Centos 为例搭建 Git 服务器。</p><h3 id="1、安装Git"><a href="#1、安装Git" class="headerlink" title="1、安装Git"></a>1、安装Git</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel</span><br><span class="line">$ yum install git</span><br></pre></td></tr></table></figure><p>接下来我们 创建一个git用户组和用户，用来运行git服务：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ groupadd git</span><br><span class="line">$ useradd git -g git</span><br></pre></td></tr></table></figure><h3 id="2、创建证书登录"><a href="#2、创建证书登录" class="headerlink" title="2、创建证书登录"></a>2、创建证书登录</h3><p>收集所有需要登录的用户的公钥，公钥位于id_rsa.pub文件中，把我们的公钥导入到/home/git/.ssh/authorized_keys文件里，一行一个。</p><p>如果没有该文件创建它：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ cd &#x2F;home&#x2F;git&#x2F;</span><br><span class="line">$ mkdir .ssh</span><br><span class="line">$ chmod 755 .ssh</span><br><span class="line">$ touch .ssh&#x2F;authorized_keys</span><br><span class="line">$ chmod 644 .ssh&#x2F;authorized_keys</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="5.png" alt="image.png"></p><h3 id="3、初始化Git仓库"><a href="#3、初始化Git仓库" class="headerlink" title="3、初始化Git仓库"></a>3、初始化Git仓库</h3><p>首先我们选定一个目录作为Git仓库，假定是/home/gitrepo/victor.git，在/home/gitrepo目录下输入命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$ cd &#x2F;home</span><br><span class="line">$ mkdir gitrepo</span><br><span class="line">$ chown git:git gitrepo&#x2F;</span><br><span class="line">$ cd gitrepo</span><br><span class="line"></span><br><span class="line">$ git init --bare victor.git</span><br><span class="line">Initialized empty Git repository in &#x2F;home&#x2F;gitrepo&#x2F;victor.git&#x2F;</span><br></pre></td></tr></table></figure><p>以上命令Git创建一个空仓库，服务器上的Git仓库通常都以.git结尾。然后，把仓库所属用户改为git：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ chown -R git:git victor.git</span><br></pre></td></tr></table></figure><h3 id="4、克隆仓库"><a href="#4、克隆仓库" class="headerlink" title="4、克隆仓库"></a>4、克隆仓库</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ git clone git@116.62.194.162:&#x2F;home&#x2F;gitrepo&#x2F;victor.git</span><br><span class="line">Cloning into &#39;victor&#39;...</span><br><span class="line">warning: You appear to have cloned an empty repository.</span><br><span class="line">Checking connectivity... done.</span><br></pre></td></tr></table></figure><p>116.62.194.162 为 Git 所在服务器 ip ，你需要将其修改为你自己的 Git 服务 ip。</p><p>这样我们的 Git 服务器安装就完成。</p><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p><a href="https://www.runoob.com/git/git-server.html">https://www.runoob.com/git/git-server.html</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> git </tag>
            
            <tag> linux </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Gradle配置阿里云镜像</title>
      <link href="develop/gradle/"/>
      <url>develop/gradle/</url>
      
        <content type="html"><![CDATA[<h1 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h1><p>Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置，目前也增加了基于Kotlin语言的kotlin-based DSL，抛弃了基于XML的各种 繁琐配置。</p><h1 id="镜像源配置"><a href="#镜像源配置" class="headerlink" title="镜像源配置"></a>镜像源配置</h1><h2 id="单个项目"><a href="#单个项目" class="headerlink" title="单个项目"></a>单个项目</h2><p>使用阿里云国内镜像</p><p>生效，在项目中的build.gradle修改内容</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">buildscript &#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        maven &#123; url <span class="string">&#x27;http://maven.aliyun.com/nexus/content/groups/public/&#x27;</span> &#125;</span><br><span class="line">                maven&#123; url <span class="string">&#x27;http://maven.aliyun.com/nexus/content/repositories/jcenter&#x27;</span>&#125;</span><br><span class="line">    &#125;</span><br><span class="line">    dependencies &#123;</span><br><span class="line">        classpath <span class="string">&#x27;com.android.tools.build:gradle:2.2.3&#x27;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// <span class="doctag">NOTE:</span> Do not place your application dependencies here; they belong</span></span><br><span class="line">        <span class="comment">// in the individual module build.gradle files</span></span><br><span class="line">    &#125;        </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">allprojects &#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        maven &#123; url <span class="string">&#x27;http://maven.aliyun.com/nexus/content/groups/public/&#x27;</span> &#125;</span><br><span class="line">        maven&#123; url <span class="string">&#x27;http://maven.aliyun.com/nexus/content/repositories/jcenter&#x27;</span>&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="默认源配置"><a href="#默认源配置" class="headerlink" title="默认源配置"></a>默认源配置</h2><p>对所有项目生效，在USER_HOME/.gradle/下创建init.gradle文件</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">allprojects&#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        <span class="keyword">def</span> ALIYUN_REPOSITORY_URL = <span class="string">&#x27;http://maven.aliyun.com/nexus/content/groups/public&#x27;</span></span><br><span class="line">        <span class="keyword">def</span> ALIYUN_JCENTER_URL = <span class="string">&#x27;http://maven.aliyun.com/nexus/content/repositories/jcenter&#x27;</span></span><br><span class="line">        <span class="keyword">def</span> GRADLE_LOCAL_RELEASE_URL = <span class="string">&#x27;https://repo.gradle.org/gradle/libs-releases-local&#x27;</span></span><br><span class="line">        <span class="keyword">def</span> ALIYUN_SPRING_RELEASE_URL = <span class="string">&#x27;https://maven.aliyun.com/repository/spring-plugin&#x27;</span></span><br><span class="line">        </span><br><span class="line">        all &#123; ArtifactRepository repo -&gt;</span><br><span class="line">            <span class="keyword">if</span>(repo <span class="keyword">instanceof</span> MavenArtifactRepository)&#123;</span><br><span class="line">                <span class="keyword">def</span> url = repo.url.toString()</span><br><span class="line">                <span class="keyword">if</span> (url.startsWith(<span class="string">&#x27;https://repo1.maven.org/maven2&#x27;</span>)) &#123;</span><br><span class="line">                    project.logger.lifecycle <span class="string">&quot;Repository $&#123;repo.url&#125; replaced by $ALIYUN_REPOSITORY_URL.&quot;</span></span><br><span class="line">                    remove repo</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (url.startsWith(<span class="string">&#x27;https://jcenter.bintray.com/&#x27;</span>)) &#123;</span><br><span class="line">                    project.logger.lifecycle <span class="string">&quot;Repository $&#123;repo.url&#125; replaced by $ALIYUN_JCENTER_URL.&quot;</span></span><br><span class="line">                    remove repo</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (url.startsWith(<span class="string">&#x27;http://repo.spring.io/plugins-release&#x27;</span>)) &#123;</span><br><span class="line">                    project.logger.lifecycle <span class="string">&quot;Repository $&#123;repo.url&#125; replaced by $ALIYUN_SPRING_RELEASE_URL.&quot;</span></span><br><span class="line">                    remove repo</span><br><span class="line">                &#125;</span><br><span class="line">                </span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        maven &#123;</span><br><span class="line">            url ALIYUN_REPOSITORY_URL     </span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        maven &#123;            </span><br><span class="line">            url ALIYUN_JCENTER_URL          </span><br><span class="line">        &#125;</span><br><span class="line">        maven &#123;            </span><br><span class="line">            url ALIYUN_SPRING_RELEASE_URL</span><br><span class="line">        &#125;</span><br><span class="line">        maven &#123;</span><br><span class="line">            url GRADLE_LOCAL_RELEASE_URL</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="网上搜集的常用仓库地址"><a href="#网上搜集的常用仓库地址" class="headerlink" title="网上搜集的常用仓库地址"></a>网上搜集的常用仓库地址</h2><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">epositories &#123;</span><br><span class="line"></span><br><span class="line">    mavenCentral()</span><br><span class="line"></span><br><span class="line">    maven &#123; url <span class="string">&quot;https://jitpack.io&quot;</span> &#125;</span><br><span class="line"></span><br><span class="line">    maven &#123; url <span class="string">&quot;http://maven.aliyun.com/nexus/content/groups/public/&quot;</span> &#125;</span><br><span class="line"></span><br><span class="line">    maven &#123; url <span class="string">&#x27;http://maven.oschina.net/content/groups/public/&#x27;</span> &#125;</span><br><span class="line"></span><br><span class="line">    maven &#123; url <span class="string">&#x27;https://oss.sonatype.org/content/repositories/snapshots/&#x27;</span> &#125;</span><br><span class="line"></span><br><span class="line">    maven &#123; url <span class="string">&quot;http://maven.springframework.org/release&quot;</span> &#125;</span><br><span class="line"></span><br><span class="line">    maven &#123; url <span class="string">&quot;http://maven.restlet.org&quot;</span> &#125;</span><br><span class="line"></span><br><span class="line">    maven &#123; url <span class="string">&quot;http://mirrors.ibiblio.org/maven2&quot;</span> &#125;</span><br><span class="line"></span><br><span class="line">    maven &#123;</span><br><span class="line"></span><br><span class="line">        url <span class="string">&quot;http://repo.baichuan-android.taobao.com/content/groups/BaichuanRepositories/&quot;</span></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    maven &#123; url <span class="string">&#x27;https://maven.fabric.io/public&#x27;</span> &#125;</span><br><span class="line"></span><br><span class="line">    jcenter()</span><br><span class="line"></span><br><span class="line">    google()</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="阿里仓库集合"><a href="#阿里仓库集合" class="headerlink" title="阿里仓库集合"></a>阿里仓库集合</h2><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">apache snapshots</span><br><span class="line">proxy</span><br><span class="line">SNAPSHOT</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/apache-snapshots</span></span><br><span class="line">central</span><br><span class="line">proxy</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/central</span></span><br><span class="line">google</span><br><span class="line">proxy</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/google</span></span><br><span class="line">gradle-plugin</span><br><span class="line">proxy</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/gradle-plugin</span></span><br><span class="line">jcenter</span><br><span class="line">proxy</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/jcenter</span></span><br><span class="line">spring</span><br><span class="line">proxy</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/spring</span></span><br><span class="line">spring-plugin</span><br><span class="line">proxy</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/spring-plugin</span></span><br><span class="line"><span class="keyword">public</span></span><br><span class="line">group</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/public</span></span><br><span class="line">releases</span><br><span class="line">hosted</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/releases</span></span><br><span class="line">snapshots</span><br><span class="line">hosted</span><br><span class="line">SNAPSHOT</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/snapshots</span></span><br><span class="line">grails-core</span><br><span class="line">proxy</span><br><span class="line">RELEASE</span><br><span class="line"><span class="attr">https:</span><span class="comment">//maven.aliyun.com/repository/grails-core</span></span><br></pre></td></tr></table></figure><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><p>build.gradle 文件内 对于 顺序有要求(注意避坑)</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>ELK启动问题解决方案</title>
      <link href="operation/elk/"/>
      <url>operation/elk/</url>
      
        <content type="html"><![CDATA[<h2 id="elk"><a href="#elk" class="headerlink" title="elk"></a>elk</h2><p>elasticsearch</p><p>lotstash</p><p>kibana</p><h1 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h1><p>报错解决:</p><ul><li><p><a href="https://blog.csdn.net/ywdhzxf/article/details/89740406">csdn</a></p></li><li><p><a href="https://blog.csdn.net/zxz9325/article/details/110262417?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control">csdn</a></p></li><li><p><a href="http://www.voidcn.com/article/p-raygpaqb-bys.html">voidcn</a></p></li></ul><h2 id="更多"><a href="#更多" class="headerlink" title="更多:"></a>更多:</h2><p><a href="http://victorfengming.gitee.io/elk/">elk课件</a></p><hr><p>版本</p><p> elasticsearch kibana logstash filebeat 都用6.8.0的哈</p><p>机器</p><p>10.221.154.185</p><p>10.221.154.186</p><p>10.221.154.187</p><p><a href="https://blog.csdn.net/yehongzhi1994/article/details/109459225">https://blog.csdn.net/yehongzhi1994/article/details/109459225</a></p><p>官网下载</p><blockquote><p>filebeat-6.8.0-linux-x86_64.tar.gz</p><p>logstash-6.8.0.tar.gz</p><p>elasticsearch-6.8.0.tar.gz</p><p>kibana-6.8.0-linux-x86_64.tar.gz</p></blockquote><p> 找到config目录下的elasticsearch.yml文件，修改配置： </p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">cluster.name:</span> <span class="number">154</span><span class="string">-es</span></span><br><span class="line"><span class="attr">node.name:</span> <span class="string">node-185</span></span><br><span class="line"><span class="attr">bootstrap.memory_lock:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">bootstrap.system_call_filter:</span> <span class="literal">false</span></span><br><span class="line"><span class="attr">network.host:</span> <span class="number">10.221</span><span class="number">.154</span><span class="number">.185</span></span><br><span class="line"><span class="attr">http.port:</span> <span class="number">9003</span></span><br><span class="line"><span class="attr">discovery.zen.ping.unicast.hosts:</span> [<span class="string">&quot;10.221.154.182&quot;</span>, <span class="string">&quot;10.221.154.183&quot;</span>]</span><br><span class="line"><span class="attr">discovery.zen.minimum_master_nodes:</span> <span class="number">2</span></span><br><span class="line"><span class="attr">node.master:</span> <span class="literal">false</span></span><br><span class="line"><span class="attr">node.data:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">node.ingest:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure><p>es配置</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">cluster.name:</span> <span class="number">154</span><span class="string">-es</span></span><br><span class="line"><span class="attr">node.name:</span> <span class="string">node-185</span></span><br><span class="line"><span class="attr">network.host:</span> <span class="number">10.221</span><span class="number">.154</span><span class="number">.185</span></span><br><span class="line"><span class="attr">http.port:</span> <span class="number">9003</span></span><br><span class="line"><span class="attr">path.data:</span> <span class="string">/opt/app/elk6.8.0/elasticsearch-6.8.0/data</span></span><br><span class="line"><span class="attr">path.logs:</span> <span class="string">/opt/app/elk6.8.0/elasticsearch-6.8.0/logs</span></span><br><span class="line"></span><br><span class="line"><span class="attr">xpack.security.enabled:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="attr">xpack.security.transport.ssl.enable:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="attr">xpack.security.transport.ssl.verification_mode:</span> <span class="string">certificate</span></span><br><span class="line"><span class="attr">xpack.security.transport.ssl.keystore.path:</span> <span class="string">/opt/app/elk6.8.0/elasticsearch-6.8.0/elastic-certificates.p12</span></span><br><span class="line"><span class="attr">xpack.security.transport.ssl.truststore.path:</span> <span class="string">/opt/app/elk6.8.0/elasticsearch-6.8.0/elastic-certificates.p12</span></span><br></pre></td></tr></table></figure><p>修改配置</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/elasticsearch-6.8.0/config/</span><br><span class="line">vi elasticsearch.yml</span><br></pre></td></tr></table></figure><p>查找替换</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">:%s&#x2F;\&#x2F;\&#x2F;&#x2F;#&#x2F;g </span><br></pre></td></tr></table></figure><p>%s全局</p><p>//  待匹配的字符</p><p><code># 要替换的字符</code></p><p>g匹配到的全替换</p><p>查找替换</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">:%s/#/\r# /g</span><br></pre></td></tr></table></figure><p>配置</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">network.host:</span> <span class="number">10.221</span><span class="number">.154</span><span class="number">.185</span></span><br><span class="line"><span class="attr">http.port:</span> <span class="number">9003</span></span><br><span class="line"><span class="attr">path:</span></span><br><span class="line">    <span class="attr">data:</span> <span class="string">/opt/app/elk6.8.0/elasticsearch-6.8.0/data</span></span><br><span class="line">    <span class="attr">logs:</span> <span class="string">/opt/app/elk6.8.0/elasticsearch-6.8.0/logs</span></span><br><span class="line"><span class="attr">bootstrap.memory_lock:</span> <span class="literal">false</span></span><br><span class="line"><span class="attr">bootstrap.system_call_filter:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="attr">xpack.security.enabled:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="attr">xpack.security.transport.ssl.enable:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="attr">xpack.security.transport.ssl.verification_mode:</span> <span class="string">certificate</span></span><br><span class="line"><span class="attr">xpack.security.transport.ssl.keystore.path:</span> <span class="string">/opt/app/elk6.8.0/elasticsearch-6.8.0/elastic-certificates.p12</span></span><br><span class="line"><span class="attr">xpack.security.transport.ssl.truststore.path:</span> <span class="string">/opt/app/elk6.8.0/elasticsearch-6.8.0/elastic-certificates.p12</span></span><br></pre></td></tr></table></figure><h1 id="elasticsearch"><a href="#elasticsearch" class="headerlink" title="elasticsearch"></a>elasticsearch</h1><h2 id="启动es"><a href="#启动es" class="headerlink" title="启动es"></a>启动es</h2><blockquote><p>ps -ef|grep ela</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd &#x2F;opt&#x2F;app&#x2F;elk6.8.0&#x2F;elasticsearch-6.8.0</span><br><span class="line"></span><br><span class="line">rm output.log</span><br><span class="line"></span><br><span class="line">nohup .&#x2F;bin&#x2F;elasticsearch &gt;&gt; output.log 2&gt;&amp;1 &amp;</span><br><span class="line"></span><br><span class="line">ps -ef|grep ela</span><br><span class="line"></span><br><span class="line">tail -f output.log</span><br></pre></td></tr></table></figure><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><p>解决1: <a href="https://blog.csdn.net/qq_21383435/article/details/108962457">es check the logs and fix your configuration or disable system call filters</a></p><h1 id="kibana"><a href="#kibana" class="headerlink" title="kibana"></a>kibana</h1><p>配置文件</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">#修改如下配置</span></span><br><span class="line"><span class="attr">server.port:</span> <span class="number">8080</span></span><br><span class="line"><span class="attr">server.host:</span> <span class="string">&quot;0.0.0.0&quot;</span></span><br><span class="line"><span class="comment">##修改为自己es的端口</span></span><br><span class="line"><span class="attr">elasticsearch.url:</span> <span class="string">&quot;http://10.221.154.185:9003&quot;</span></span><br><span class="line"><span class="attr">kibana.index:</span> <span class="string">&quot;.kibana&quot;</span></span><br><span class="line"><span class="attr">i18n.locale:</span> <span class="string">&quot;zh-CN&quot;</span><span class="comment"># 配置中文 6.7以后版本可直接配置</span></span><br></pre></td></tr></table></figure><p>启动脚本</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">cd &#x2F;opt&#x2F;app&#x2F;elk6.8.0&#x2F;kibana-6.8.0-linux-x86_64&#x2F;bin</span><br><span class="line"></span><br><span class="line">rm output.log</span><br><span class="line"></span><br><span class="line">nohup .&#x2F;kibana &gt;&gt; output.log 2&gt;&amp;1 &amp;</span><br><span class="line"></span><br><span class="line">ps -ef|grep kibana</span><br></pre></td></tr></table></figure><hr><h1 id="filebeat"><a href="#filebeat" class="headerlink" title="filebeat"></a>filebeat</h1><h2 id="完整-filebeat-logstash-ES"><a href="#完整-filebeat-logstash-ES" class="headerlink" title="完整 filebeat-logstash-ES"></a>完整 filebeat-logstash-ES</h2><p>10.221.154.188</p><p><a href="https://www.cnblogs.com/lwx57280/p/13742433.html">https://www.cnblogs.com/lwx57280/p/13742433.html</a></p><p>配值</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/filebeat-6.8.0-linux-x86_64</span><br><span class="line"></span><br><span class="line">vi f2l2e-log.yml</span><br></pre></td></tr></table></figure><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">log</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">paths:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/opt/applog/*.log</span></span><br><span class="line">  <span class="attr">tags:</span> [<span class="string">&quot;web&quot;</span>, <span class="string">&quot;test&quot;</span>]</span><br><span class="line">  <span class="attr">fields:</span></span><br><span class="line">    <span class="attr">from:</span> <span class="string">test-web</span></span><br><span class="line">  <span class="attr">fields_under_root:</span> <span class="literal">false</span></span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">1</span></span><br><span class="line"><span class="attr">output.logstash:</span></span><br><span class="line">  <span class="attr">hosts:</span> [<span class="string">&quot;10.221.154.186:5044&quot;</span>]</span><br><span class="line"><span class="attr">setup.kibana:</span></span><br><span class="line">  <span class="attr">hosts:</span> <span class="string">&quot;10.221.154.187:8080&quot;</span></span><br></pre></td></tr></table></figure><p>启动</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/filebeat-6.8.0-linux-x86_64</span><br><span class="line"></span><br><span class="line">rm output1.log</span><br><span class="line"></span><br><span class="line">nohup ./filebeat -e -c ./f2l2e-log.yml  &gt;&gt; output1.log 2&gt;&amp;1 &amp;</span><br><span class="line"><span class="meta">#</span><span class="bash"> -e 标准启动 -c 指定配置文件</span></span><br><span class="line">ps -ef|grep filebeat</span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/applog/</span><br><span class="line"></span><br><span class="line">echo &quot;victor279&quot; &gt;&gt; q.log</span><br></pre></td></tr></table></figure><h2 id="测试-filebeat-ES"><a href="#测试-filebeat-ES" class="headerlink" title="测试 filebeat-ES"></a>测试 filebeat-ES</h2><p>配值</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/filebeat-6.8.0-linux-x86_64</span><br><span class="line"></span><br><span class="line">vi f2e-log.yml</span><br></pre></td></tr></table></figure><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">log</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">paths:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/opt/applog/*.log</span></span><br><span class="line">  <span class="attr">tags:</span> [<span class="string">&quot;web&quot;</span>, <span class="string">&quot;test&quot;</span>]</span><br><span class="line">  <span class="attr">fields:</span></span><br><span class="line">    <span class="attr">from:</span> <span class="string">test-web</span></span><br><span class="line">  <span class="attr">fields_under_root:</span> <span class="literal">false</span> </span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">1</span></span><br><span class="line"><span class="attr">output.elasticsearch:</span></span><br><span class="line">  <span class="attr">hosts:</span> [<span class="string">&quot;10.221.154.185:9003&quot;</span>]</span><br></pre></td></tr></table></figure><p>启动</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/filebeat-6.8.0-linux-x86_64</span><br><span class="line"></span><br><span class="line">rm output2.log</span><br><span class="line"></span><br><span class="line">nohup ./filebeat -e -c ./f2e-log.yml  &gt;&gt; output2.log 2&gt;&amp;1 &amp;</span><br><span class="line"><span class="meta">#</span><span class="bash"> -e 标准启动 -c 指定配置文件</span></span><br><span class="line"></span><br><span class="line">ps -ef|grep filebeat</span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/applog/</span><br><span class="line"></span><br><span class="line">echo &quot;victor990&quot; &gt;&gt; c.log</span><br></pre></td></tr></table></figure><p>ELK : <a href="https://blog.csdn.net/beyond_qjm/article/details/81943187">https://blog.csdn.net/beyond_qjm/article/details/81943187</a></p><h1 id="Logstash"><a href="#Logstash" class="headerlink" title="Logstash"></a>Logstash</h1><h2 id="完整-filebeat-logstash-ES-1"><a href="#完整-filebeat-logstash-ES-1" class="headerlink" title="完整 filebeat-logstash-ES"></a>完整 filebeat-logstash-ES</h2><p><a href="https://blog.csdn.net/beyond_qjm/article/details/81945527">https://blog.csdn.net/beyond_qjm/article/details/81945527</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> ./logstash -f ../config/logstash-sample.conf</span> </span><br><span class="line"></span><br><span class="line">cd /opt/app/elk6.8.0/logstash-6.8.0/</span><br><span class="line"></span><br><span class="line">rm output.log</span><br><span class="line"></span><br><span class="line">nohup ./bin/logstash -f ./config/f2l2e-pipelines.yml   &gt;&gt; output.log 2&gt;&amp;1 &amp;</span><br><span class="line"></span><br><span class="line">ps -ef|grep logstash</span><br><span class="line"></span><br><span class="line">tail -f output.log</span><br></pre></td></tr></table></figure><hr><h2 id="测试-logstash-ES"><a href="#测试-logstash-ES" class="headerlink" title="测试 logstash-ES"></a>测试 logstash-ES</h2><hr><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">input</span> &#123;</span><br><span class="line">    <span class="string">file</span> &#123;</span><br><span class="line">        <span class="string">path</span> <span class="string">=&gt;</span> <span class="string">&quot;/opt/applog/*.log&quot;</span></span><br><span class="line">        <span class="string">start_position</span> <span class="string">=&gt;</span> <span class="string">&quot;beginning&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="string">filter</span> &#123;</span><br><span class="line">    <span class="string">mutate</span> &#123;</span><br><span class="line">        <span class="string">split</span> <span class="string">=&gt;</span> &#123;<span class="string">&quot;message&quot;</span><span class="string">=&gt;&quot;|&quot;</span>&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="string">output</span> &#123;</span><br><span class="line">    <span class="string">elasticsearch</span> &#123;</span><br><span class="line">        <span class="string">hosts</span> <span class="string">=&gt;</span> [<span class="string">&quot;10.221.154.185:9003&quot;</span>]</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/logstash-6.8.0</span><br><span class="line"></span><br><span class="line">rm output.log</span><br><span class="line"></span><br><span class="line">nohup ./bin/logstash -f ./config/l2e-piplines.yml  &gt;&gt; output.log 2&gt;&amp;1 &amp;</span><br><span class="line"></span><br><span class="line">ps -ef|grep logstash</span><br><span class="line"></span><br><span class="line">cat output.log</span><br></pre></td></tr></table></figure><hr><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/applog/</span><br><span class="line"></span><br><span class="line">echo &quot;victor494&quot; &gt;&gt; f.log</span><br></pre></td></tr></table></figure><h2 id="input-from-filebeat"><a href="#input-from-filebeat" class="headerlink" title="input from filebeat"></a>input from filebeat</h2><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">input</span> &#123;</span><br><span class="line">   <span class="string">beats</span> &#123;</span><br><span class="line">     <span class="string">port</span> <span class="string">=&gt;</span> <span class="number">5044</span>   <span class="comment">#要监听的端口</span></span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="string">filter</span> &#123;</span><br><span class="line">    <span class="string">mutate</span> &#123;</span><br><span class="line">        <span class="string">split</span> <span class="string">=&gt;</span> &#123;<span class="string">&quot;message&quot;</span><span class="string">=&gt;&quot;|&quot;</span>&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="string">output</span> &#123;</span><br><span class="line">    <span class="string">elasticsearch</span> &#123;</span><br><span class="line">        <span class="string">hosts</span> <span class="string">=&gt;</span> [<span class="string">&quot;10.221.154.185:9003&quot;</span>]</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/logstash-6.8.0</span><br><span class="line"></span><br><span class="line">rm output.log</span><br><span class="line"></span><br><span class="line">nohup ./bin/logstash -f ./config/f2l2e-pipelines.yml  &gt;&gt; output.log 2&gt;&amp;1 &amp;</span><br><span class="line"></span><br><span class="line">ps -ef|grep logstash</span><br><span class="line"></span><br><span class="line">tail -f output.log</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/applog/</span><br><span class="line"></span><br><span class="line">echo &quot;victor991&quot; &gt;&gt; f.log</span><br></pre></td></tr></table></figure><h1 id="todo"><a href="#todo" class="headerlink" title="todo"></a>todo</h1><p>单独测试 </p><p>filebeat 连 logstash</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">touch f2l-pipelines.yml</span><br></pre></td></tr></table></figure><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">input</span> &#123;</span><br><span class="line">   <span class="string">beats</span> &#123;</span><br><span class="line">     <span class="string">port</span> <span class="string">=&gt;</span> <span class="number">5044</span>   <span class="comment">#要监听的端口</span></span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="string">output</span> &#123;</span><br><span class="line">    <span class="string">stdout</span> &#123; <span class="string">codec</span> <span class="string">=&gt;</span> <span class="string">rubydebug</span> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/logstash-6.8.0</span><br><span class="line"></span><br><span class="line">rm output.log</span><br><span class="line"></span><br><span class="line">nohup ./bin/logstash -f ./config/f2l-pipelines.yml  &gt;&gt; output.log 2&gt;&amp;1 &amp;</span><br><span class="line"></span><br><span class="line">ps -ef|grep logstash</span><br></pre></td></tr></table></figure><hr><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">log</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">paths:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/opt/applog/*.log</span></span><br><span class="line">  <span class="attr">tags:</span> [<span class="string">&quot;web&quot;</span>, <span class="string">&quot;test&quot;</span>]</span><br><span class="line">  <span class="attr">fields:</span></span><br><span class="line">    <span class="attr">from:</span> <span class="string">test-web</span></span><br><span class="line">  <span class="attr">fields_under_root:</span> <span class="literal">false</span></span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">1</span></span><br><span class="line"><span class="attr">output.logstash:</span></span><br><span class="line">  <span class="attr">hosts:</span> [<span class="string">&quot;10.221.154.186:5044&quot;</span>]</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/app/elk6.8.0/filebeat-6.8.0-linux-x86_64</span><br><span class="line"></span><br><span class="line">rm output.log</span><br><span class="line"></span><br><span class="line">nohup ./filebeat -e -c ./f2l-log.yml  &gt;&gt; output1.log 2&gt;&amp;1 &amp;</span><br><span class="line"><span class="meta">#</span><span class="bash"> -e 标准启动 -c 指定配置文件</span></span><br><span class="line">ps -ef|grep filebeat</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> elk </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Gitbook安装问题</title>
      <link href="git/gitbook/"/>
      <url>git/gitbook/</url>
      
        <content type="html"><![CDATA[<p>安装gitbook ,由于原来的 安装环境中的文件没有删除干净,导致一直安装不上,</p><p>只需要将对应的文件删除了即可</p><p>现在解决就</p><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">E:\Projects\IdeaProjects\gitbook\other_gitbook&gt;</span><br><span class="line">E:\Projects\IdeaProjects\gitbook\other_gitbook&gt;npm install -g gitbook-cli</span><br><span class="line">npm WARN rollback Rolling back is-fullwidth-code-point@2.0.0 failed (this is probably harmless): EPERM: operation not permitted, lstat &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbo</span><br><span class="line">ok-cli\node_modules\npm\node_modules\update-notifier\node_modules\boxen\node_modules\string-width\node_modules&#x27;</span><br><span class="line">npm WARN rollback Rolling back strip-ansi@4.0.0 failed (this is probably harmless): EPERM: operation not permitted, lstat &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\node_m</span><br><span class="line">odules\npm\node_modules\update-notifier\node_modules\boxen\node_modules\string-width\node_modules&#x27;</span><br><span class="line">npm WARN rollback Rolling back number-is-nan@1.0.1 failed (this is probably harmless): EPERM: operation not permitted, lstat &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\nod</span><br><span class="line">e_modules\npm\node_modules\update-notifier\node_modules\boxen\node_modules\widest-line\node_modules\string-width\node_modules\is-fullwidth-code-point\node_modules&#x27;</span><br><span class="line">npm WARN rollback Rolling back copy-concurrently@1.0.3 failed (this is probably harmless): EPERM: operation not permitted, lstat &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli</span><br><span class="line">\node_modules\npm\node_modules\move-concurrently\node_modules&#x27;</span><br><span class="line">npm WARN rollback Rolling back has-ansi@2.0.0 failed (this is probably harmless): EPERM: operation not permitted, scandir &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\node_m</span><br><span class="line">odules\npm\node_modules\update-notifier\node_modules\chalk\node_modules&#x27;</span><br><span class="line">npm WARN rollback Rolling back defaults@1.0.3 failed (this is probably harmless): EPERM: operation not permitted, lstat &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\node_mod</span><br><span class="line">ules\npm\node_modules\columnify\node_modules\wcwidth\node_modules&#x27;</span><br><span class="line">npm WARN rollback Rolling back registry-url@3.1.0 failed (this is probably harmless): EPERM: operation not permitted, scandir &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\no</span><br><span class="line">de_modules\npm\node_modules\update-notifier\node_modules\latest-version\node_modules\package-json\node_modules&#x27;</span><br><span class="line">npm WARN rollback Rolling back asn1@0.2.3 failed (this is probably harmless): EPERM: operation not permitted, scandir &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\node_modul</span><br><span class="line">es\npmi\node_modules\npm\node_modules\request\node_modules\http-signature\node_modules\sshpk\node_modules&#x27;</span><br><span class="line">npm WARN rollback Rolling back http-signature@1.1.1 failed (this is probably harmless): EPERM: operation not permitted, scandir &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\</span><br><span class="line">node_modules\npmi\node_modules\npm\node_modules\request\node_modules&#x27;</span><br><span class="line">npm ERR! code EEXIST</span><br><span class="line">npm ERR! path C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\bin\gitbook.js</span><br><span class="line">npm ERR! dest C:\Users\Administrator\AppData\Roaming\npm\gitbook</span><br><span class="line">npm ERR! EEXIST: file already exists, cmd shim &#x27;C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\bin\gitbook.js&#x27; -&gt; &#x27;C:\Users\Administrator\AppData\Roaming\npm\gitbook&#x27;</span><br><span class="line">npm ERR! File exists: C:\Users\Administrator\AppData\Roaming\npm\gitbook</span><br><span class="line">npm ERR! Remove the existing file and try again, or run npm</span><br><span class="line">npm ERR! with --force to overwrite files recklessly.</span><br><span class="line"></span><br><span class="line">npm ERR! A complete log of this run can be found in:</span><br><span class="line">npm ERR!     C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2021-02-04T13_02_46_864Z-debug.log</span><br><span class="line"></span><br><span class="line">E:\Projects\IdeaProjects\gitbook\other_gitbook&gt;npm install -g gitbook-cli</span><br><span class="line">C:\Users\Administrator\AppData\Roaming\npm\gitbook -&gt; C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\bin\gitbook.js</span><br><span class="line">+ gitbook-cli@2.3.2</span><br><span class="line">added 578 packages from 672 contributors in 16.351s</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="第二个问题"><a href="#第二个问题" class="headerlink" title="第二个问题"></a>第二个问题</h3><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">E:\Projects\IdeaProjects\gitbook\other_gitbook&gt;gitbook -V</span><br><span class="line">CLI version: 2.3.2</span><br><span class="line">Installing GitBook 3.2.3</span><br><span class="line">C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\node_modules\npm\node_modules\graceful-fs\polyfills.js:287</span><br><span class="line">      if (cb) cb.apply(this, arguments)</span><br><span class="line">                 ^</span><br><span class="line"></span><br><span class="line">TypeError: cb.apply is not a function</span><br><span class="line">    at C:\Users\Administrator\AppData\Roaming\npm\node_modules\gitbook-cli\node_modules\npm\node_modules\graceful-fs\polyfills.js:287:18</span><br><span class="line">    at FSReqCallback.oncomplete (fs.js:169:5)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>这行代码就是检查的,没鸡儿用</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">statFix</span> (<span class="params">orig</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (!orig) <span class="keyword">return</span> orig</span><br><span class="line">  <span class="comment">// Older versions of Node erroneously returned signed integers for</span></span><br><span class="line">  <span class="comment">// uid + gid.</span></span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params">target, cb</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> orig.call(fs, target, <span class="function"><span class="keyword">function</span> (<span class="params">er, stats</span>) </span>&#123;</span><br><span class="line">      <span class="keyword">if</span> (!stats) <span class="keyword">return</span> cb.apply(<span class="built_in">this</span>, <span class="built_in">arguments</span>)</span><br><span class="line">      <span class="keyword">if</span> (stats.uid &lt; <span class="number">0</span>) stats.uid += <span class="number">0x100000000</span></span><br><span class="line">      <span class="keyword">if</span> (stats.gid &lt; <span class="number">0</span>) stats.gid += <span class="number">0x100000000</span></span><br><span class="line">      <span class="comment">// if (cb) cb.apply(this, arguments)</span></span><br><span class="line">      <span class="comment">// 直接就给他注释掉,完美!perfect </span></span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>注意</strong></p><p>这里不能直接注释 掉if (cb) cb.apply(this, arguments)</p><p>需要注释掉62-64行</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// fs.stat = statFix(fs.stat)</span></span><br><span class="line"><span class="comment">// fs.fstat = statFix(fs.fstat)</span></span><br><span class="line"><span class="comment">// fs.lstat = statFix(fs.lstat)</span></span><br></pre></td></tr></table></figure><p>看完这些commit的记录</p><p>物是人非</p><p>19 20 21年的提交都在这里</p><p>刻出了时光的痕迹</p>]]></content>
      
      
      
        <tags>
            
            <tag> gitbook </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>如何绕过dgrijalva/jwt go中的cve-2020-26160漏洞</title>
      <link href="golang/fiber/jwt-bug/"/>
      <url>golang/fiber/jwt-bug/</url>
      
        <content type="html"><![CDATA[<h1 id="如何绕过dgrijalva-jwt-go中的cve-2020-26160漏洞"><a href="#如何绕过dgrijalva-jwt-go中的cve-2020-26160漏洞" class="headerlink" title="如何绕过dgrijalva/jwt go中的cve-2020-26160漏洞"></a>如何绕过dgrijalva/jwt go中的cve-2020-26160漏洞</h1><p>如何绕过dgrijalva/jwt go中的cve-2020-26160漏洞？</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">go</span> jwt jwt-<span class="keyword">go</span></span><br></pre></td></tr></table></figure><p>由于存在一个高级漏洞，Gitlab管道中无法传递容器安全状态。此漏洞为jwt-go，安装的版本为v3.2.0+incompatible。错误标题如下：jwt-go: access restriction bypass vulnerability–&gt;avd.aquasec.com/nvd/cve-2020-26160。相关回购协议的Go版本为1.16.3。如何修复此漏洞？</p><p>CVE-2020-26160漏洞是由于dgrijalva/jwt-go错误地将JWTaud字段建模为string，而基于JWT规范，它应该是字符串的一部分。</p><p>在一般情况下，“aud”值是case-sensitive字符串的数组</p><p>你自己不能绕过它，因为它是库中的一个bug：<code>https://github.com/dgrijalva/jwt-go/issues/428</code></p><p>切换到官方社区分支golang-jwt/jwt，其v3.2.1修复了漏洞：<code>https://github.com/golang-jwt/jwt/releases/tag/v3.2.1</code></p><p>导入路径更改：有关更新代码的提示，请参见MIGRATION_GUIDE.md，将导入路径从<code>github.com/dgrijalva/jwt-go</code>更改为<code>github.com/golang-jwt/jwt</code><br>修复了VerifyAudience（#12）中字符串和[]字符串之间的类型混淆问题。这修复了CVE-2020-26160</p><p>原文连接: <a href="https://www.5axxw.com/questions/content/o849sj">https://www.5axxw.com/questions/content/o849sj</a></p><p>文档地址: <a href="https://docs.gofiber.io/">https://docs.gofiber.io/</a></p><h1 id="helloworld"><a href="#helloworld" class="headerlink" title="helloworld"></a>helloworld</h1><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;github.com/gofiber/fiber/v2&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">app := fiber.New()</span><br><span class="line"></span><br><span class="line">app.Get(<span class="string">&quot;/&quot;</span>, <span class="function"><span class="keyword">func</span><span class="params">(c *fiber.Ctx)</span> <span class="title">error</span></span> &#123;</span><br><span class="line"><span class="keyword">return</span> c.SendString(<span class="string">&quot;Hello, World!&quot;</span>)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.Listen(<span class="string">&quot;:3000&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="其他案例"><a href="#其他案例" class="headerlink" title="其他案例"></a>其他案例</h1><ul><li><a href="https://gitee.com/victorfengming/fiber-demo/">fiber-demo</a></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> Golang </tag>
            
            <tag> Web </tag>
            
            <tag> Fiber </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>DDD领域驱动设计实战</title>
      <link href="comic/architecture-design/"/>
      <url>comic/architecture-design/</url>
      
        <content type="html"><![CDATA[<h1 id="DDD1-课程介绍"><a href="#DDD1-课程介绍" class="headerlink" title="DDD1-课程介绍"></a>DDD1-课程介绍</h1><h2 id="互联网大厂的蔚来架构之道"><a href="#互联网大厂的蔚来架构之道" class="headerlink" title="互联网大厂的蔚来架构之道"></a>互联网大厂的蔚来架构之道</h2><p>DDD领域驱动设计 实战</p><p>阿里ddd: cola</p><p>DDD天生就适合微服务的这种方式</p><p>阿里中台的概念</p><p>很多企业发现在践行中台的战略中遇到很多问题</p><blockquote><p>提升软件质量</p></blockquote><hr><h2 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h2><p>DDD是一个庞大的理论体系,如何落地是一个问题,而不像微服务体系或者MVC架构有这么多框架</p><p>很多大厂是用这种小型的项目用DDD来进行推广</p><p>DDD要求于具体的技术无关的</p><hr><h2 id="目录"><a href="#目录" class="headerlink" title="目录"></a>目录</h2><p><img src= "/img/loading.gif" data-lazy-src="1629338118966.png" alt="1629338118966"></p><p><img src= "/img/loading.gif" data-lazy-src="1629338198960.png" alt="1629338198960"></p><p>技术学起来很快,想要与众不同,就需要你的软实力,这种软实力的提升就是比较虚的</p><p>DDD适合贯穿于你的整个体系</p><ul><li><img src= "/img/loading.gif" data-lazy-src="https://s1.hdslb.com/bfs/static/jinkela/video/asserts/playing.gif" alt="img">P22.</li></ul><h1 id="DDD2-什么是DDD"><a href="#DDD2-什么是DDD" class="headerlink" title="DDD2-什么是DDD"></a>DDD2-什么是DDD</h1><p>  17:40</p><h2 id="啥时DDD"><a href="#啥时DDD" class="headerlink" title="啥时DDD"></a>啥时DDD</h2><p><img src= "/img/loading.gif" data-lazy-src="1629338564960.png" alt="1629338564960"></p><p>NoSql: redis mongodb hbase </p><p>nosql概念是这个作者提出来的</p><p>软件设计的复杂性,要复杂才能适合ddd</p><hr><p>不如在进行权限控制的时候,我们就会简历RBAC</p><p>,通过角色来简历权限控制,就是一种ddd</p><h2 id="实现领域驱动设计"><a href="#实现领域驱动设计" class="headerlink" title="实现领域驱动设计"></a>实现领域驱动设计</h2><hr><p><img src= "/img/loading.gif" data-lazy-src="1629339244610.png" alt="1629339244610"></p><h1 id="DDD3-系统老化谁的锅"><a href="#DDD3-系统老化谁的锅" class="headerlink" title="DDD3-系统老化谁的锅"></a>DDD3-系统老化谁的锅</h1><p>  11:28</p><h2 id="什么是系统老化"><a href="#什么是系统老化" class="headerlink" title="什么是系统老化"></a>什么是系统老化</h2><p>迭代时间很长的项目</p><p>比如一个项目迭代了10多年</p><h2 id="系统老化"><a href="#系统老化" class="headerlink" title="系统老化"></a>系统老化</h2><p><img src= "/img/loading.gif" data-lazy-src="1629340114232.png" alt="1629340114232"></p><p>人员变更,</p><p>新的人员如何去理解业务需求</p><p>文档一般还是跟不上的</p><hr><p>重构否??? 重构了没有实质性的提升,成本却很高</p><h2 id="微服务架构能防止系统变老么"><a href="#微服务架构能防止系统变老么" class="headerlink" title="微服务架构能防止系统变老么"></a>微服务架构能防止系统变老么</h2><p><img src= "/img/loading.gif" data-lazy-src="1629340539762.png" alt="1629340539762"></p><p>随着微服务的发展</p><p>还是会出现没有这种实质性的该变</p><p>局部业务出现膨胀 还是需要重构, 还是需要拆分</p><p>微服务架构会一定程度上的解决,但是还是不会根本解决,只会让你的老化速度变慢一点儿</p><hr><p>DDD理论体系</p><h1 id="DDD4-转账功能改造上"><a href="#DDD4-转账功能改造上" class="headerlink" title="DDD4-转账功能改造上"></a>DDD4-转账功能改造上</h1><p>  21:03</p><p>写出一个小demo</p><h2 id="于浩代码的差距到底在哪"><a href="#于浩代码的差距到底在哪" class="headerlink" title="于浩代码的差距到底在哪"></a>于浩代码的差距到底在哪</h2><hr><p><img src= "/img/loading.gif" data-lazy-src="1629340761309.png" alt="1629340761309"></p><p><img src= "/img/loading.gif" data-lazy-src="1629340847009.png" alt="1629340847009"></p><p><img src= "/img/loading.gif" data-lazy-src="1629340861574.png" alt="1629340861574"></p><p><img src= "/img/loading.gif" data-lazy-src="1629340872021.png" alt="1629340872021"></p><p>这样的代码实际上是面相过程的方式</p><p>也被称之为事务脚本</p><p>先不考虑他的执行效果</p><p>写高质量的代码: 高内聚 低耦合</p><p>需要可行的标准: </p><p>单一职责原则:(一个模块只做一个业务)</p><p>开放封闭原则:对扩展开放,对修改封闭</p><p>依赖翻转原则: 面相接口依赖,而不是依赖具体的实现类</p><h2 id="抽象数据存储层"><a href="#抽象数据存储层" class="headerlink" title="抽象数据存储层"></a>抽象数据存储层</h2><p><img src= "/img/loading.gif" data-lazy-src="1629341310457.png" alt="1629341310457"></p><p><img src= "/img/loading.gif" data-lazy-src="1629341335070.png" alt="1629341335070"></p><p>把业务方法写到 实体里面</p><p>DDD里面提到的充血模型</p><p>与之对应的 称为 贫血模型&gt;&gt;&gt; POJO Martin Fowler 提出来的(就是只有属性和get set 方法的实体类)</p><blockquote><p>我们这个实体本来是为了承载业务来设计的,但是</p><p>最后变成从这个实体根本看不出有哪些业务了,这种称为贫血失忆症</p><p>如和解决: 充血模型</p></blockquote><p><img src= "/img/loading.gif" data-lazy-src="1629341860503.png" alt="1629341860503"></p><p>可以在定义一个实体,来实现,比如修改密码,修改xxx的业务,这个实体只做他的事情: 转入转出操作</p><hr><p>定义的时候就比较别扭了</p><p>到底什么方法要加入实体类中</p><p>DDD中对这个Business是有说道的</p><p>业务是对于实体改变的</p><p>而这种转账是不会改变实体的</p><blockquote><p>Order -&gt; OrderItem -&gt; Address</p></blockquote><p>整体于部分的关系,</p><hr><p>把仓库定义成巨大无比的对象池</p><p>理想: 所有对象都在内存对象池里</p><p>如果有大对象,就需要工厂来 帮助改造</p><h1 id="DDD5-转账功能改造下"><a href="#DDD5-转账功能改造下" class="headerlink" title="DDD5-转账功能改造下"></a>DDD5-转账功能改造下</h1><p>  24:52</p><h2 id="抽象第三方服务"><a href="#抽象第三方服务" class="headerlink" title="抽象第三方服务"></a>抽象第三方服务</h2><p><img src= "/img/loading.gif" data-lazy-src="1629350158455.png" alt="1629350158455"></p><p><img src= "/img/loading.gif" data-lazy-src="1629350169915.png" alt="1629350169915"></p><p>你的第三方服务怎么实现的和我的业务没有关系</p><blockquote><p>DDD中的防腐层ACL: 隔离第三方的依赖</p></blockquote><h2 id="抽象第三方组件"><a href="#抽象第三方组件" class="headerlink" title="抽象第三方组件"></a>抽象第三方组件</h2><p><img src= "/img/loading.gif" data-lazy-src="1629350386261.png" alt="1629350386261"></p><p><img src= "/img/loading.gif" data-lazy-src="1629351563267.png" alt="1629351563267"></p><h2 id="DDD4层架构"><a href="#DDD4层架构" class="headerlink" title="DDD4层架构"></a>DDD4层架构</h2><p><img src= "/img/loading.gif" data-lazy-src="1629352294652.png" alt="1629352294652"></p><blockquote><p>DDD的一大特点,当你的业务绝对简单的时候,</p><p>在小型的业务下,往往体现不出优势</p></blockquote><h1 id="DDD6-DDD项目改造"><a href="#DDD6-DDD项目改造" class="headerlink" title="DDD6-DDD项目改造"></a>DDD6-DDD项目改造</h1><p>  16:53</p><h1 id="DDD7-DDD项目改造"><a href="#DDD7-DDD项目改造" class="headerlink" title="DDD7-DDD项目改造"></a>DDD7-DDD项目改造</h1><p>  25:22</p><h2 id="“DDD”Vs-DDD项目改造"><a href="#“DDD”Vs-DDD项目改造" class="headerlink" title="“DDD”Vs DDD项目改造"></a>“DDD”Vs DDD项目改造</h2><p><img src= "/img/loading.gif" data-lazy-src="1629353459610.png" alt="1629353459610"></p><h1 id="DDD8-DDD项目改造下"><a href="#DDD8-DDD项目改造下" class="headerlink" title="DDD8-DDD项目改造下"></a>DDD8-DDD项目改造下</h1><p>  11:02</p><p><img src= "/img/loading.gif" data-lazy-src="1629354275521.png" alt="1629354275521"></p><p>“DDD”,data driven design</p><h1 id="DDD9-DDD视角下的单体架构与微服务架构"><a href="#DDD9-DDD视角下的单体架构与微服务架构" class="headerlink" title="DDD9-DDD视角下的单体架构与微服务架构"></a>DDD9-DDD视角下的单体架构与微服务架构</h1><p>  13:46</p><h2 id="微服务时代-单体架构淘汰了吗"><a href="#微服务时代-单体架构淘汰了吗" class="headerlink" title="微服务时代,单体架构淘汰了吗"></a>微服务时代,单体架构淘汰了吗</h2><p><img src= "/img/loading.gif" data-lazy-src="1629356649627.png" alt="1629356649627"></p><h2 id="DDD视角下单体架构与微服务架构的统一"><a href="#DDD视角下单体架构与微服务架构的统一" class="headerlink" title="DDD视角下单体架构与微服务架构的统一"></a>DDD视角下单体架构与微服务架构的统一</h2><p><img src= "/img/loading.gif" data-lazy-src="1629360817198.png" alt="1629360817198"></p><h1 id="DDD10-DDD发展展望"><a href="#DDD10-DDD发展展望" class="headerlink" title="DDD10-DDD发展展望"></a>DDD10-DDD发展展望</h1><p>  17:46</p><h2 id="中台-DDD的另一片战场"><a href="#中台-DDD的另一片战场" class="headerlink" title="中台,DDD的另一片战场"></a>中台,DDD的另一片战场</h2><p><img src= "/img/loading.gif" data-lazy-src="1629360930637.png" alt="1629360930637"></p><blockquote><p>战略工具,DDD提供 的方法 形成一个统一的语言</p></blockquote><p>平台+资源调度&gt;-&gt;- 中台</p><p><img src= "/img/loading.gif" data-lazy-src="1629361977397.png" alt="1629361977397"></p><p><img src= "/img/loading.gif" data-lazy-src="1629362358998.png" alt="1629362358998"></p><hr><h1 id="from"><a href="#from" class="headerlink" title="from"></a>from</h1><p><a href="https://www.bilibili.com/video/BV1Y341167Xp?from=search&amp;seid=8938952084618205028">https://www.bilibili.com/video/BV1Y341167Xp?from=search&amp;seid=8938952084618205028</a></p><p>2小时掌握宇宙最强DDD（Data Display Debugger）DDD领域驱动设计实战</p><hr><p><img src= "/img/loading.gif" data-lazy-src="1631600715895.png" alt="1631600715895"></p><p><img src= "/img/loading.gif" data-lazy-src="1631600712581.png" alt="1631600712581"></p>]]></content>
      
      
      
        <tags>
            
            <tag> DDD </tag>
            
            <tag> base </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Kafka速度快的原因</title>
      <link href="cp/why-kafka-fast/"/>
      <url>cp/why-kafka-fast/</url>
      
        <content type="html"><![CDATA[<p>读写2方面:</p><h2 id="写-tv-發財"><a href="#写-tv-發財" class="headerlink" title="写: tv_發財"></a>写: tv_發財</h2><pre><code>    1. 顺序存储:           -  顺序写入,去掉了比较耗费时间的磁盘寻址的过程,这个磁盘的顺序读写速度甚至超过内存的随机读写           -  顺序写入,jvm的GC效率低,内存占用大, 使用磁盘可以避免这个问题,相比(在内存中操作)           -  顺序写入,系统冷启动后,磁盘缓存依然可用 (linux对于磁盘的读写也有优化,比如磁盘缓存)            不删除数据:后的2种策略:           -   顺序写入一是基于时间。           -   顺序写入二是基于partition文件大小。    2. 分页存储:           - 数据写入不实时,利用现代操作系统的分页存储来利用内存提高IO效率.            Memory Mapped Files(后面简称mmap)也被翻译成 内存映射文件 ，在64位操作系统中一般可以表示            20G的数据文件，它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。` 完成映射之后你对物理内存的操作会被同步到硬盘上（操作系统在适当的时候）</code></pre><h2 id="读-tv-呆"><a href="#读-tv-呆" class="headerlink" title="读: tv_呆"></a>读: tv_呆</h2><pre><code>    1. 零拷贝            Kafka使用零拷贝(Zero-Copy)技术来提供它的性能，所谓的零拷贝是指将数据直接从磁盘文件复制到网卡设备中，而                                            不需要经由应用程序之手，减少了内核和用户模式之间的上下文切换，零拷贝技术通过DMA技术实现。   2.  消息压缩            因为网络IO更可能成为瓶颈,所以利用少量的cpu资源进行压缩是有必要的           2.1、如果每个消息都压缩，但是压缩率相对很低，所以Kafka使用了批量压缩，即将多个消息一起压缩                而不是单个消息压缩            2.2、Kafka允许使用递归的消息集合，批量的消息可以通过压缩的形式传输并且在日志中也可以保持压                    缩格式，直到被消费者解压缩            2.3、Kafka支持多种压缩协议，包括Gzip和Snappy压缩协议</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> kafka </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>The Plan Of Java Training</title>
      <link href="index/train/"/>
      <url>index/train/</url>
      
        <content type="html"><![CDATA[<table><thead><tr><th><a href="https://victorfengming.gitee.io/index/gitbook/">Go</a></th><th>完成度</th><th></th><th></th></tr></thead><tbody><tr><td>01.第一阶段 开源框架源码解析（完结）</td><td></td><td></td><td></td></tr><tr><td>–&gt; 01.模块一 持久层框架设计及MyBatis源码分析,<a href="https://victorfengming.gitee.io/file/pdf/mybatis/lagou_mybatis.pdf">课件</a></td><td></td><td></td><td>2021/5/18</td></tr><tr><td>–&gt;–&gt; <a href="http://victorfengming.gitee.io/mybatis/lagou/01_%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%81%E4%B9%85%E5%B1%82%E6%A1%86%E6%9E%B6/">01.任务一：自定义持久层框架</a></td><td>85</td><td></td><td>2021/5/19</td></tr><tr><td>–&gt;–&gt; <a href="http://victorfengming.gitee.io/mybatis/lagou/02_MyBatis%E5%9F%BA%E7%A1%80%E5%9B%9E%E9%A1%BE%E5%8F%8A%E9%AB%98%E7%BA%A7%E5%BA%94%E7%94%A8/#01--mybatis%E7%9B%B8%E5%85%B3%E6%A6%82%E5%BF%B5%E5%9B%9E%E9%A1%BEvep">02.任务二：MyBatis基础回顾及高级应用</a></td><td>85</td><td></td><td>2021/5/20</td></tr><tr><td>–&gt;–&gt; <a href="http://victorfengming.gitee.io/mybatis/lagou/03_MyBatis%E6%BA%90%E7%A0%81%E5%89%96%E6%9E%90/">03.任务三：MyBatis源码剖析</a></td><td>35</td><td></td><td>2021/5/21</td></tr><tr><td>–&gt;–&gt; <a href="https://victorfengming.gitee.io/mybatis/lagou/04_%E6%A8%A1%E5%9D%97%E4%BD%9C%E4%B8%9A/">04.任务四：模块作业</a></td><td>15</td><td></td><td>2021/5/22</td></tr><tr><td>–&gt;–&gt; 05.直播答疑回放</td><td>0</td><td></td><td>2021/5/23</td></tr><tr><td>–&gt;–&gt; 选修：<a href="https://victorfengming.gitee.io/mybatis/lagou/05_Mybatis-Plus/">MyBatis-Plus应用</a></td><td>65</td><td>13/30</td><td>2021/5/23</td></tr><tr><td>–&gt; 02.模块二 IoC容器设计实现及Spring源码分析,<a href="https://victorfengming.gitee.io/file/pdf/spring/lagou_spring.pdf">课件</a></td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：自定义IoC&amp;AOP框架</td><td></td><td>5/14</td><td>2021/5/24</td></tr><tr><td>–&gt;–&gt; 02.任务二：Spring IoC高级应用与源码剖析</td><td>0</td><td></td><td>2021/5/25</td></tr><tr><td>–&gt;–&gt; 03.任务三：Spring AOP高级应用与源码剖析</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 04.任务四：模块作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 03.模块三 <a href="http://victorfengming.gitee.io/spring/">MVC框架设计实现及SpringMVC源码分析、通用数据操作接口设计及SpringData 接口规范</a></td><td>0</td><td></td><td>2021/5/26</td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td>0</td><td></td><td>2021/5/27</td></tr><tr><td>–&gt;–&gt; 01.任务一： SpringMVC基础回顾及其高级深入</td><td>0</td><td></td><td>2021/5/28</td></tr><tr><td>–&gt;–&gt; 02.任务二：自定义MVC框架</td><td>0</td><td></td><td>2021/5/29</td></tr><tr><td>–&gt;–&gt; 03.任务三：SpringMVC源码剖析及其SSM整合</td><td>0</td><td></td><td>2021/5/30</td></tr><tr><td>–&gt;–&gt; 04.任务四：SpringData高级 应用及其源码剖析</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.任务五：模块作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 04.模块四 <a href="http://victorfengming.gitee.io/springboot/">约定优于配置设计范式及Spring Boot源码剖析 SpringBoot缓存管理之自定义RedisCache</a></td><td>0</td><td></td><td>2021/5/31</td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td>0</td><td></td><td>2021/6/1</td></tr><tr><td>–&gt;–&gt; 01.任务一：SpringBoot基础回顾</td><td>0</td><td></td><td>2021/6/2</td></tr><tr><td>–&gt;–&gt; 02.任务二：SpringBoot源码剖析</td><td>0</td><td></td><td>2021/6/3</td></tr><tr><td>–&gt;–&gt; 03.任务三：SpringBoot高级进阶</td><td>0</td><td></td><td>2021/6/4</td></tr><tr><td>–&gt;–&gt; 04.任务四：模板作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>02.第二阶段 Web服务器深度应用及调优（完结）</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 01.模块一 Tomcat深度剖析及性能调优、Nginx深度剖析及性能调优</td><td>0</td><td></td><td>2021/6/5</td></tr><tr><td>–&gt;–&gt; 01.任务一：Tomcat高级使用及其原理剖析</td><td>0</td><td></td><td>2021/6/6</td></tr><tr><td>–&gt;–&gt; 02.任务二：Tomcat源码剖析及调优</td><td>0</td><td></td><td>2021/6/7</td></tr><tr><td>–&gt;–&gt; 03.任务三：<a href="https://victorfengming.gitee.io/nginx/">Nginx原理深入剖析</a></td><td>0</td><td></td><td>2021/6/8</td></tr><tr><td>–&gt;–&gt; 04.任务四：模块作业</td><td>0</td><td></td><td>2021/6/9</td></tr><tr><td>–&gt;–&gt; 05.直播答疑回放</td><td>0</td><td></td><td>2021/6/10</td></tr><tr><td>–&gt; 02.模块二 Cluster模式潜在问题及解决方案、Web服务综合解决方案</td><td>0</td><td></td><td>2021/6/14</td></tr><tr><td>–&gt;–&gt; 00.资料</td><td>0</td><td></td><td>2021/6/15</td></tr><tr><td>–&gt;–&gt; 01.任务一：一致性Hash问题及解决方案</td><td>0</td><td></td><td>2021/6/16</td></tr><tr><td>–&gt;–&gt; 02.任务二：分布式集群时钟同步问题及解决方案</td><td>0</td><td></td><td>2021/6/17</td></tr><tr><td>–&gt;–&gt; 03.任务三：分布式ID问题及解决方案</td><td>0</td><td></td><td>2021/6/18</td></tr><tr><td>–&gt;–&gt; 04.任务四：分布式调度问题及解决方案</td><td>0</td><td></td><td>2021/6/19</td></tr><tr><td>–&gt;–&gt; 05.任务五：Session一致性问题及解决方案</td><td>0</td><td></td><td>2021/6/20</td></tr><tr><td>–&gt;–&gt; 06.任务六：模块作业</td><td>0</td><td></td><td>2021/6/21</td></tr><tr><td>–&gt;–&gt; 07.直播答疑回放</td><td>0</td><td></td><td>2021/6/22</td></tr><tr><td>03.第三阶段 分布式架构设计&amp;微服务深入剖析（完结）</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 01.模块一 分布式理论、架构设计（自定义RPC）</td><td>0</td><td></td><td>2021/6/23</td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：基础理论及一致性算法</td><td>0</td><td></td><td>2021/6/24</td></tr><tr><td>–&gt;–&gt; 02.任务二：分布式系统设计策略</td><td>0</td><td></td><td>2021/6/25</td></tr><tr><td>–&gt;–&gt; 03.任务三：分布式架构网络通信及自定义RPC</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 04.任务四：模块作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 02.模块二 <a href="https://victorfengming.gitee.io/zookeeper/">分布式服务治理、分布式协调服务Zookeeper深入</a></td><td>0</td><td></td><td>2021/6/26</td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：Zookeeper环境搭建和基本使用</td><td>0</td><td></td><td>2021/6/27</td></tr><tr><td>–&gt;–&gt; 02.任务二：Zookeeper应用场景和深入进阶</td><td></td><td></td><td>2021/6/28</td></tr><tr><td>–&gt;–&gt; 03.任务三：Zookeeper源码剖析</td><td>0</td><td></td><td>2021/6/29</td></tr><tr><td>–&gt;–&gt; 04.任务四：模块作业</td><td>0</td><td></td><td>2021/6/30</td></tr><tr><td>–&gt;–&gt; 05.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 03.模块三 高性能RPC框架Apache Dubbo</td><td></td><td></td><td>2021/6/29</td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：架构演变及Dubbo使用回顾</td><td>0</td><td></td><td>2021/6/30</td></tr><tr><td>–&gt;–&gt; 02.任务二：Dubbo深入配置和高级实战</td><td>0</td><td></td><td>2021/7/1</td></tr><tr><td>–&gt;–&gt; 03.任务三：Dubbo架构设计和源码剖析</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 04.任务四：模块作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 04.模块四 <a href="https://victorfengming.gitee.io/springcloud/">SpringCloud组件设计原理及实战-上</a></td><td>00</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：微服务架构与SpringCloud概述</td><td>0</td><td></td><td>2021/7/2</td></tr><tr><td>–&gt;–&gt; 02.任务二：微服务案例引入及问题剖析</td><td>0</td><td></td><td>2021/7/3</td></tr><tr><td>–&gt;–&gt; 03.任务三：SpringCloud核心组件原理及实战（上）</td><td>0</td><td></td><td>2021/7/4</td></tr><tr><td>–&gt;–&gt; 04.任务四：SpringCloud核心组件原理及实战（中）</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.任务五：SpringCloud核心组件原理及实战（下）</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.任务六：模块作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 07.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 05.模块五 SpringCloud组件设计原理及实战（下）</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：Spring Cloud高级实战</td><td>0</td><td></td><td>2021/7/5</td></tr><tr><td>–&gt;–&gt; 02.任务二：Spring Cloud Alibaba高级实战</td><td>0</td><td></td><td>2021/7/6</td></tr><tr><td>–&gt;–&gt; 03.任务三：模块作业</td><td>0</td><td></td><td>2021/7/7</td></tr><tr><td>–&gt;–&gt; 04.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>04.第四阶段 大型分布式存储系统架构进阶（完结）</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 模块一：<a href="https://victorfengming.gitee.io/course/mysql/index.html">MySQL海量数据存储与优化-上</a></td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 00.资料</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：MySQL架构原理</td><td>0</td><td></td><td>2021/7/8</td></tr><tr><td>–&gt;–&gt; 02.任务二：MySQL索引原理</td><td>0</td><td></td><td>2021/7/9</td></tr><tr><td>–&gt;–&gt; 03.任务三：MySQL事务和锁</td><td>0</td><td></td><td>2021/7/10</td></tr><tr><td>–&gt;–&gt; 05.任务四：MySQL集群架构</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.扩展：MySQL性能优化</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 07.任务五：模块作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 08.模块一直播【回放】</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 模块二：MySQL海量数据存储与优化（下）</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 00.资料</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：分库分表实战</td><td>0</td><td></td><td>2021/7/11</td></tr><tr><td>–&gt;–&gt; 02.任务二：ShardingSphere实战</td><td></td><td></td><td>2021/7/12</td></tr><tr><td>–&gt;–&gt; 03.任务三：Mycat实战</td><td></td><td></td><td>2021/7/13</td></tr><tr><td>–&gt;–&gt; 04.任务四：运维工具</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.任务五：模块作业</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.模块二直播回放</td><td></td><td></td><td></td></tr><tr><td>–&gt; 模块三：分布式文档存储独角兽MongoDB、知识图谱存储数据库Neo4j</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：分布式文档存储MongoDB</td><td></td><td></td><td>2021/7/14</td></tr><tr><td>–&gt;–&gt; 02.任务二：知识图谱存储Neo4j</td><td></td><td></td><td>2021/7/15</td></tr><tr><td>–&gt;–&gt; 03.任务三：模块作业</td><td></td><td></td><td>2021/7/16</td></tr><tr><td>–&gt;–&gt; 04.直播回放</td><td></td><td></td><td></td></tr><tr><td>–&gt; 模块四：轻量级分布式文件系统FastDFS、阿里云OSS云存储平台</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 00.资料</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：轻量级分布式文件系统FastDFS</td><td></td><td></td><td>2021/7/17</td></tr><tr><td>–&gt;–&gt; 02.任务二：阿里云OSS云存储平台</td><td></td><td></td><td>2021/7/18</td></tr><tr><td>–&gt;–&gt; 03.模块作业</td><td></td><td></td><td>2021/7/19</td></tr><tr><td>–&gt;–&gt; 04.直播</td><td></td><td></td><td></td></tr><tr><td>–&gt; 模块五：<a href="http://victorfengming.gitee.io/hadoop/">Hadoop分布式文件系统HDFS、海量列式存储数据库HBase</a></td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：Hadoop简介及Apache Hadoop完全分布式集群搭建</td><td>0</td><td></td><td>2021/7/20</td></tr><tr><td>–&gt;–&gt; 02.任务二：HDFS分布式文件系统</td><td></td><td></td><td>2021/7/21</td></tr><tr><td>–&gt;–&gt; 03.任务三：MapReduce分布式计算框架</td><td>0</td><td></td><td>2021/7/22</td></tr><tr><td>–&gt;–&gt; 04.任务四：YARN资源调度、HDFS核心源码及Hadoop3.X 新特性概述</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.任务五：海量列式存储数据库HBase</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.任务六：模块作业</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 07.直播答疑回放</td><td>0</td><td></td><td></td></tr><tr><td>05.第五阶段 大型分布式系统缓存架构进阶（完结）</td><td></td><td></td><td></td></tr><tr><td>–&gt; 01.模块一 <a href="http://victorfengming.gitee.io/redis/">高性能分布式缓存Redis、分布式 Redis 解决方案Codis-Twemproxy替代方案</a></td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：缓存原理&amp;设计</td><td>0</td><td></td><td>2021/7/23</td></tr><tr><td>–&gt;–&gt; 02.任务二：Redis底层结构和缓存原理</td><td></td><td></td><td>2021/7/24</td></tr><tr><td>–&gt;–&gt; 03.任务三：Redis通讯协议和事件处理机制</td><td>0</td><td></td><td>2021/7/25</td></tr><tr><td>–&gt;–&gt; 04.任务四：Redis持久化机制和扩展功能</td><td>0</td><td></td><td>2021/7/26</td></tr><tr><td>–&gt;–&gt; 05.任务五：Redis分布式高可用方案</td><td></td><td></td><td>2021/7/27</td></tr><tr><td>–&gt;–&gt; 06.任务六：企业实战和大厂面试</td><td></td><td></td><td>2021/7/28</td></tr><tr><td>–&gt;–&gt; 07.任务七：模块作业</td><td></td><td></td><td>2021/7/29</td></tr><tr><td>–&gt;–&gt; 08.加餐：Codis集群搭建</td><td></td><td></td><td>2021/7/30</td></tr><tr><td>–&gt;–&gt; 09.模块一直播回放</td><td></td><td></td><td>2021/7/31</td></tr><tr><td>–&gt; 02.模块二 Guava Cache、EVCache、Tair、Aerospike</td><td>0</td><td></td><td>2021/8/1</td></tr><tr><td>–&gt;–&gt; 00.课程资料</td><td></td><td></td><td>2021/8/2</td></tr><tr><td>–&gt;–&gt; 01.任务一：Guava Cache</td><td>0</td><td></td><td>2021/8/3</td></tr><tr><td>–&gt;–&gt; 02.任务二：EVCache</td><td></td><td></td><td>2021/8/4</td></tr><tr><td>–&gt;–&gt; 03.任务三：Tair</td><td></td><td></td><td>2021/8/5</td></tr><tr><td>–&gt;–&gt; 04.任务四：Aerospike</td><td>0</td><td></td><td>2021/8/6</td></tr><tr><td>–&gt;–&gt; 05.任务五：模块作业</td><td></td><td></td><td>2021/8/7</td></tr><tr><td>06.第六阶段 分布式消息服务中间件进阶（完结）</td><td></td><td></td><td></td></tr><tr><td>–&gt; 01.模块一 <a href="https://victorfengming.gitee.io/rabbit_mq/">开源消息中间件RabbitMQ</a></td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：消息中间件概述</td><td></td><td></td><td>2021/8/8</td></tr><tr><td>–&gt;–&gt; 02.任务二：RabbitMQ架构与实战</td><td>0</td><td></td><td>2021/8/9</td></tr><tr><td>–&gt;–&gt; 03.任务三：RabbitMQ高级特性解析</td><td></td><td></td><td>2021/8/10</td></tr><tr><td>–&gt;–&gt; 04.任务四：RabbitMQ集群与运维</td><td></td><td></td><td>2021/8/11</td></tr><tr><td>–&gt;–&gt; 05.任务五：RabbitMQ源码剖析</td><td>0</td><td></td><td>2021/8/12</td></tr><tr><td>–&gt;–&gt; 06.任务六：模块作业</td><td></td><td></td><td>2021/8/13</td></tr><tr><td>–&gt;–&gt; 07.模块一直播【回放】</td><td>0</td><td></td><td>2021/8/14</td></tr><tr><td>–&gt;–&gt; 08.模块一【课程资料】</td><td></td><td></td><td></td></tr><tr><td>–&gt; 02.模块二 高吞吐消息中间件Kafka</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：Kafka架构与实战</td><td>0</td><td></td><td>2021/8/14</td></tr><tr><td>–&gt;–&gt; 02.任务二：Kafka高级特性解析</td><td></td><td></td><td>2021/8/15</td></tr><tr><td>–&gt;–&gt; 03.任务三：Kafka集群与运维</td><td>0</td><td></td><td>2021/8/16</td></tr><tr><td>–&gt;–&gt; 04.任务四：Kafka源码剖析</td><td></td><td></td><td>2021/8/17</td></tr><tr><td>–&gt;–&gt; 05.任务五：模块作业</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.模块二直播【回放】</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 07.模块二【课程资料】</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 03.模块三 Apache消息中间件RocketMQ</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：RocketMQ架构与实战</td><td></td><td></td><td>2021/8/18</td></tr><tr><td>–&gt;–&gt; 02.任务二：RocketMQ高级特性及原理</td><td></td><td></td><td>2021/8/19</td></tr><tr><td>–&gt;–&gt; 03.任务三：RocketMQ高级实战</td><td>0</td><td></td><td>2021/8/20</td></tr><tr><td>–&gt;–&gt; 04.任务四：RocketMQ集群与运维</td><td></td><td></td><td>2021/8/21</td></tr><tr><td>–&gt;–&gt; 05.任务五：RocketMQ源码剖析</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.任务六：模块作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 07.模块三直播【回放】</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 08.模块三【课程资料】</td><td>0</td><td></td><td></td></tr><tr><td>07.第七阶段 分布式搜索引擎进阶（完结）</td><td></td><td></td><td></td></tr><tr><td>–&gt; 01.模块一 引擎工具包Lucene、搜索应用服务器Solr</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：引擎工具包Lucene</td><td></td><td></td><td>2021/8/22</td></tr><tr><td>–&gt;–&gt; 02.任务二：搜索应用服务器Solr</td><td>0</td><td></td><td>2021/8/23</td></tr><tr><td>–&gt;–&gt; 03.模块一【课程资料】</td><td>0</td><td></td><td>2021/8/24</td></tr><tr><td>–&gt; 02.模块二 <a href="https://victorfengming.gitee.io/elk/">海量日志分析平台Elastic Stack</a></td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：Elasticsearch快速实战</td><td></td><td></td><td>2021/8/25</td></tr><tr><td>–&gt;–&gt; 02.任务二：Elasticsearch高级应用</td><td>0</td><td></td><td>2021/8/26</td></tr><tr><td>–&gt;–&gt; 03.任务三：Elasticsearch集群与高级实战</td><td></td><td></td><td>2021/8/27</td></tr><tr><td>–&gt;–&gt; 04.任务四：Elasticsearch之深度应用及原理剖析</td><td>0</td><td></td><td>2021/8/28</td></tr><tr><td>–&gt;–&gt; 05.模块作业</td><td>0</td><td></td><td>2021/8/29</td></tr><tr><td>–&gt;–&gt; 06.模块二直播【回放】</td><td></td><td></td><td>2021/8/30</td></tr><tr><td>–&gt;–&gt; 07.模块二【课程资料】</td><td>0</td><td></td><td></td></tr><tr><td>08.第八阶段 分布式实时流式计算引擎Flink（完结）</td><td></td><td></td><td></td></tr><tr><td>–&gt; 01.模块一 分布式实时流式计算引擎Flink</td><td>0</td><td></td><td>2021/8/31</td></tr><tr><td>–&gt;–&gt; 01.任务一：Flink快速应用及基础原理</td><td>0</td><td></td><td>2021/9/1</td></tr><tr><td>–&gt;–&gt; 02.任务二：Flink常用API</td><td>0</td><td></td><td>2021/9/2</td></tr><tr><td>–&gt;–&gt; 03.任务三：窗口_水印_并行度_连接器</td><td>0</td><td></td><td>2021/9/3</td></tr><tr><td>–&gt;–&gt; 04.任务四：实战案例</td><td>0</td><td></td><td>2021/9/4</td></tr><tr><td>–&gt;–&gt; 05.【课程资料】</td><td></td><td></td><td>2021/9/5</td></tr><tr><td>09.第九阶段 容器技术&amp;CI_CD、DevOps（完结）</td><td></td><td></td><td>2021/9/6</td></tr><tr><td>–&gt; 01.模块一 <a href="http://victorfengming.gitee.io/docker/">Docker容器虚拟化技术</a></td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：Docker快速入门</td><td></td><td></td><td>2021/9/13</td></tr><tr><td>–&gt;–&gt; 02.任务二：Docker核心原理</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 03.任务三：Docker运维管理</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 04.第九阶段模块一作业</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.【课程资料】</td><td></td><td></td><td></td></tr><tr><td>–&gt; 02.模块二 <a href="http://victorfengming.gitee.io/kubernetes/">K8s容器编排系统</a></td><td></td><td></td><td>2021/9/14</td></tr><tr><td>–&gt;–&gt; 01.任务一：Kubernetes快速实战</td><td></td><td></td><td>2021/9/15</td></tr><tr><td>–&gt;–&gt; 02.任务二：Kubernetes核心原理</td><td>0</td><td></td><td>2021/9/16</td></tr><tr><td>–&gt;–&gt; 03.任务三：Kubernetes运维管理</td><td>0</td><td></td><td>2021/9/17</td></tr><tr><td>–&gt;–&gt; 04.模块二作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.模块一、二直播</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.模块二【课程资料】</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 03.模块三 CI_CD、DevOps</td><td>0</td><td></td><td>2021/9/18</td></tr><tr><td>–&gt;–&gt; 01.任务一：CICD、Devops概述</td><td></td><td></td><td>2021/9/19</td></tr><tr><td>–&gt;–&gt; 02.任务二：<a href="https://victorfengming.gitee.io/jenkins/">Jenkins概述与安装</a></td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 03.任务三：Jenkins环境搭建</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 04.任务四：Jenkins项目实战</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 05.任务五：Jenkins运维管理</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 06.【课程资料】</td><td></td><td></td><td></td></tr><tr><td>–&gt; 04.模块四 APM管理和性能监控工具</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 01.任务一：APM管理工具Skywalking</td><td></td><td></td><td>2021/9/20</td></tr><tr><td>–&gt;–&gt; 02.任务二：性能监控工具Pinpoint</td><td>0</td><td></td><td>2021/9/21</td></tr><tr><td>–&gt;–&gt; 03.任务三：代码质量管理工具Sonar</td><td></td><td></td><td>2021/9/22</td></tr><tr><td>–&gt;–&gt; 04.【课程资料】</td><td>0</td><td></td><td></td></tr><tr><td>10.第十阶段 底层调优与算法深入</td><td></td><td></td><td></td></tr><tr><td>–&gt; 模块一：<a href="http://victorfengming.gitee.io/data_algorithm/">数据结构、算法</a></td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 任务一：数据结构与算法基础</td><td></td><td></td><td>2021/9/23</td></tr><tr><td>–&gt;–&gt; 任务二：数据结构与算法高级</td><td>0</td><td></td><td>2021/9/24</td></tr><tr><td>–&gt;–&gt; 模块一作业</td><td></td><td></td><td>2021/9/25</td></tr><tr><td>–&gt;–&gt; 直播</td><td></td><td></td><td>2021/9/26</td></tr><tr><td>–&gt;–&gt; 数据结构与算法.zip</td><td>0</td><td></td><td>2021/9/27</td></tr><tr><td>–&gt; 模块二：并发编程、JVM优化、Linux优化</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 任务一：并发编程</td><td>0</td><td></td><td>2021/9/30</td></tr><tr><td>–&gt;–&gt; 任务三：Linux优化</td><td>-0</td><td></td><td>2021/10/1</td></tr><tr><td>–&gt;–&gt; 任务二：JVM优化</td><td>0</td><td></td><td>2021/10/2</td></tr><tr><td>–&gt;–&gt; 模块二直播【回放】</td><td></td><td></td><td>2021/10/3</td></tr><tr><td>–&gt;–&gt; 第十阶段模块二作业</td><td></td><td></td><td>2021/10/4</td></tr><tr><td>–&gt;–&gt; 课程资料.zip</td><td></td><td></td><td>2021/10/5</td></tr><tr><td>11.第十一阶段 大型互联网项目实战和业务解决方案（完结）</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 模块一：大型互联网项目开发实战和解决方案</td><td></td><td></td><td></td></tr><tr><td>–&gt;–&gt; 任务一：系统需求和设计</td><td>0</td><td></td><td>2021/10/16</td></tr><tr><td>–&gt;–&gt; 任务七：系统开发-消息模块</td><td>0</td><td></td><td>2021/10/17</td></tr><tr><td>–&gt;–&gt; 任务三：系统开发-用户模块</td><td></td><td></td><td>2021/10/18</td></tr><tr><td>–&gt;–&gt; 任务二：系统开发-广告模块</td><td></td><td></td><td>2021/10/19</td></tr><tr><td>–&gt;–&gt; 任务五：系统开发-订单和支付</td><td></td><td></td><td>2021/10/20</td></tr><tr><td>–&gt;–&gt; 任务八：系统开发-Seata分布式事务</td><td>0</td><td></td><td>2021/10/21</td></tr><tr><td>–&gt;–&gt; 任务六：系统开发-权限模块</td><td>0</td><td></td><td>2021/10/22</td></tr><tr><td>–&gt;–&gt; 任务四：系统开发-课程模块</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 第十一阶段模块一作业</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 数据库.zip</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 项目资料.zip</td><td>0</td><td></td><td></td></tr><tr><td>–&gt; 模块二：大型互联网项目系统发布和环境监控</td><td>0</td><td></td><td></td></tr><tr><td>–&gt;–&gt; 任务一：系统功能发布和压测</td><td>0</td><td></td><td>2021/10/23</td></tr><tr><td>–&gt;–&gt; 任务二：系统环境部署和监控</td><td>0</td><td></td><td>2021/10/24</td></tr><tr><td>–&gt;–&gt; 十一阶段直播【回放】</td><td></td><td></td><td>2021/10/25</td></tr><tr><td>–&gt;–&gt; 第十一阶段模块二作业</td><td></td><td></td><td>2021/10/26</td></tr><tr><td>–&gt;–&gt; 项目实战.zip</td><td>0</td><td></td><td>2021/10/27</td></tr><tr><td>12.第十二阶段 进大厂必备-面试求职深度辅导（完结）</td><td></td><td></td><td>2021/10/28</td></tr><tr><td>–&gt; 模块一：进大厂必备-面试求职深度辅导</td><td>0</td><td></td><td>2021/10/31</td></tr><tr><td>–&gt;–&gt; 任务一： 就业须知</td><td></td><td></td><td>2021/11/1</td></tr><tr><td>–&gt;–&gt; 任务三： 面试技巧</td><td>0</td><td></td><td>2021/11/2</td></tr><tr><td>–&gt;–&gt; 任务二： 面试准备</td><td></td><td></td><td>2021/11/3</td></tr><tr><td>–&gt;–&gt; 任务四： 面试总结</td><td>0</td><td></td><td>2021/11/4</td></tr><tr><td>–&gt;–&gt; 大厂面试题</td><td></td><td></td><td>2021/11/18</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> index </tag>
            
            <tag> java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python实现猴子爬山算法</title>
      <link href="python/collection/monkey_climbing/"/>
      <url>python/collection/monkey_climbing/</url>
      
        <content type="html"><![CDATA[<p>猴子爬山一只顽猴在一座有N级台阶的小山上爬山跳跃。上山时需从山脚至山顶往上跳N级台阶，一步可跳1级，或跳3级，求上山有多少种不同的跳法？ （N&lt;50）</p><p>问题分析:</p><p> 每一次都可以选择1,2,3有3种跳法</p><p>直接使用递归</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">jumpWay = [<span class="number">1</span>, <span class="number">3</span>]</span><br><span class="line"></span><br><span class="line">footstep = <span class="built_in">int</span>(<span class="built_in">input</span>())</span><br><span class="line"></span><br><span class="line">jumping = <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#first write</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">jump</span>(<span class="params">nowstep, footstep, jumpWay</span>):</span></span><br><span class="line">    <span class="keyword">if</span> nowstep == footstep:</span><br><span class="line">        <span class="keyword">global</span> jumping</span><br><span class="line">        jumping += <span class="number">1</span></span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    <span class="keyword">elif</span> nowstep &gt; footstep:</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(jumpWay)):</span><br><span class="line">            jump(nowstep + jumpWay[i], footstep, jumpWay)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">jump(<span class="number">0</span>, footstep, jumpWay)</span><br></pre></td></tr></table></figure><p>但是这种方式会提示 递归层数过多</p><p>想办法对算法进行合理优化,排列组合</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">size = <span class="built_in">int</span>(<span class="built_in">input</span>())</span><br><span class="line">n3 = size//<span class="number">3</span></span><br><span class="line">res = <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 求阶乘</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">jiecheng</span>(<span class="params">n</span>):</span></span><br><span class="line">    num = <span class="number">1</span></span><br><span class="line">    <span class="keyword">if</span> n==<span class="number">1</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>,n+<span class="number">1</span>):</span><br><span class="line">            num*=i</span><br><span class="line">        <span class="keyword">return</span> num</span><br><span class="line"></span><br><span class="line"><span class="comment"># 求排列</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">c43</span>(<span class="params">n4,n3</span>):</span></span><br><span class="line">    <span class="comment"># return jiecheng</span></span><br><span class="line">    <span class="comment"># 3!/(4-3)!*3!</span></span><br><span class="line">    <span class="comment"># j3 = jiecheng(3)</span></span><br><span class="line">    <span class="keyword">return</span> jiecheng(n4)//(jiecheng(n4-n3)*jiecheng(n3))</span><br><span class="line"></span><br><span class="line"><span class="comment"># a32不用了</span></span><br><span class="line"><span class="comment"># def a32(n3,n2):</span></span><br><span class="line"><span class="comment">#    return jiecheng(n2)//jiecheng(n3)-jiecheng(n2)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 循环</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(size+<span class="number">1</span>):</span><br><span class="line">    <span class="comment"># i 为有几个 1步的情况</span></span><br><span class="line">    <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(n3+<span class="number">1</span>):</span><br><span class="line">        <span class="comment"># j为有 几个 3步的情况</span></span><br><span class="line">        <span class="keyword">if</span> (i+j*<span class="number">3</span>) == size:</span><br><span class="line">            <span class="comment"># temp 为总数</span></span><br><span class="line">            temp = j+i</span><br><span class="line">            res+=c43(temp,j)</span><br><span class="line">print(res)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>面试题大全</title>
      <link href="index/interview/"/>
      <url>index/interview/</url>
      
        <content type="html"><![CDATA[<h3 id="数据库相关"><a href="#数据库相关" class="headerlink" title="数据库相关"></a>数据库相关</h3><ul><li><a href="https://www.cnblogs.com/bypp/p/7755307.html">MySQL索引原理以及查询优化</a></li><li><a href="https://www.cnblogs.com/curedfisher/p/12529670.html">MySQL索引的理解</a></li><li><a href="https://blog.csdn.net/xdc17824032252/article/details/94118980">栈中的方法peek()和pop()的比较</a></li></ul><h2 id="interview"><a href="#interview" class="headerlink" title="interview"></a>interview</h2><h3 id="ApacheDubbo"><a href="#ApacheDubbo" class="headerlink" title="ApacheDubbo"></a>ApacheDubbo</h3><ul><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ApacheDubbo/dubbo%E6%9C%8D%E5%8A%A1%E7%9B%B8%E5%85%B3%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">dubbo服务相关面试题</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ApacheDubbo/%E7%AE%80%E8%BF%B0dubbo%E7%9A%84spi%E6%80%9D%E6%83%B3.pdf">简述dubbo的spi思想</a><h3 id="CAS"><a href="#CAS" class="headerlink" title="CAS"></a>CAS</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/CAS/%E8%B0%88%E4%B8%80%E8%B0%88%E5%AF%B9CAS%E7%9A%84%E7%90%86%E8%A7%A3.pdf">谈一谈对CAS的理解</a><h3 id="container"><a href="#container" class="headerlink" title="container"></a>container</h3><h3 id="data-algorithm"><a href="#data-algorithm" class="headerlink" title="data_algorithm"></a>data_algorithm</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/HashMap%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E7%BA%BF%E7%A8%8B%E4%B8%8D%E5%AE%89%E5%85%A8.pdf">HashMap为什么是线程不安全</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98.pdf">八皇后问题</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E5%A6%82%E4%BD%95%E8%A1%A1%E9%87%8F%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E7%9A%84%E6%95%88%E7%8E%87%EF%BC%9F.pdf">如何衡量程序运行的效率？</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">快速排序算法面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E6%89%BE%E5%87%BA%E4%B8%8D%E9%87%8D%E5%A4%8D%E7%9A%84%E6%95%B4%E6%95%B0.pdf">找出不重复的整数</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E6%B1%82%E4%B8%AD%E4%BD%8D%E6%95%B0.pdf">求中位数</a><h3 id="design-pattern"><a href="#design-pattern" class="headerlink" title="design_pattern"></a>design_pattern</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/design_pattern/DDD%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">DDD面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/design_pattern/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">代理模式面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/design_pattern/%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BA%86%E8%A7%A3%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E5%90%97.pdf">你真的了解单例模式吗</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/design_pattern/%E7%A9%BA%E5%AF%B9%E8%B1%A1%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.pdf">空对象设计模式</a><h3 id="distributed-theory"><a href="#distributed-theory" class="headerlink" title="distributed_theory"></a>distributed_theory</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E4%BB%80%E4%B9%88%E6%98%AF%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9_%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%AA%E5%B4%A9%E7%9A%84%E5%9C%BA%E6%99%AF%E4%B8%8E%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.pdf">什么是缓存雪崩_服务器雪崩的场景与解决方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E4%BB%8E%E5%8D%95%E4%BD%93%E6%9E%B6%E6%9E%84_%E5%88%B0SOA_%E5%86%8D%E5%88%B0%E5%BE%AE%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E8%AF%A6%E8%A7%A3.pdf">从单体架构_到SOA_再到微服务的架构设计详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8FSession%E5%85%B1%E4%BA%AB%E7%9A%844%E7%B1%BB%E6%8A%80%E6%9C%AF%E6%96%B9%E6%A1%88_%E4%B8%8E%E4%BC%98%E5%8A%A3%E5%8A%BF%E6%AF%94%E8%BE%83.pdf">分布式Session共享的4类技术方案_与优劣势比较</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">分布式事务面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7%E7%9A%84%E5%8E%9F%E7%90%86%E4%B8%8E%E6%8A%80%E6%9C%AF%E5%AE%9E%E7%8E%B0%E6%96%B9%E6%A1%88.pdf">分布式数据库数据一致性的原理与技术实现方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8F%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%B9%82%E7%AD%89%E6%80%A7%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">分布式服务接口的幂等性面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E7%9A%84%E5%87%A0%E7%A7%8D%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F.pdf">分布式锁的几种实现方式</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E8%B0%88%E8%B0%88%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%9B%B8%E5%85%B3%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%E4%B8%8E%E5%AE%9E%E6%88%98%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.pdf">谈谈分布式事务相关的一致性与实战解决方案</a><h3 id="docker"><a href="#docker" class="headerlink" title="docker"></a>docker</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/docker/%E8%AF%B4%E4%B8%80%E4%B8%8B%E4%BD%A0%E5%AF%B9docker%E7%9A%84%E4%BA%86%E8%A7%A3.pdf">说一下你对docker的了解</a><h3 id="ES"><a href="#ES" class="headerlink" title="ES"></a>ES</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ES/es%E5%9C%A8%E6%95%B0%E6%8D%AE%E9%87%8F%E5%BE%88%E5%A4%A7%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B_%E6%95%B0%E5%8D%81%E4%BA%BF%E7%BA%A7%E5%88%AB_%E5%A6%82%E4%BD%95%E6%8F%90%E9%AB%98%E6%9F%A5%E8%AF%A2%E6%95%88%E7%8E%87.pdf">es在数据量很大的情况下_数十亿级别_如何提高查询效率</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ES/ES%E7%9A%84%E6%95%B0%E6%8D%AE%E8%AF%BB%E5%8F%96%E8%BF%87%E7%A8%8B%E4%BB%A5%E5%8F%8A%E6%96%87%E6%A1%A3%E8%AF%BB%E5%86%99%E5%8E%9F%E7%90%86%E5%A4%A7%E8%87%B4%E5%88%86%E6%9E%90%E4%B8%80%E4%B8%8B.pdf">ES的数据读取过程以及文档读写原理大致分析一下</a><h3 id="HashMap"><a href="#HashMap" class="headerlink" title="HashMap"></a>HashMap</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/HashMap/HashMap%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86.pdf">HashMap底层原理</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/HashMap/Hash%E5%86%B2%E7%AA%81%E6%9C%89%E4%BB%80%E4%B9%88%E8%A7%A3%E5%86%B3%E6%96%B9%E5%BC%8F.pdf">Hash冲突有什么解决方式</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/HashMap/%E9%9D%A2%E8%AF%95%E9%A2%98-HashMap.pdf">面试题-HashMap</a><h3 id="IO"><a href="#IO" class="headerlink" title="IO"></a>IO</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/IO/JavaIO%E6%B5%81%E9%9D%A2%E8%AF%95.pdf">JavaIO流面试</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/IO/%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E9%9B%B6%E6%8B%B7%E8%B4%9D.pdf">如何实现零拷贝</a><h3 id="JDK"><a href="#JDK" class="headerlink" title="JDK"></a>JDK</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JDK/%E5%8F%8D%E5%B0%84%E7%9B%B8%E5%85%B3%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">反射相关面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JDK/%E8%AE%B2%E4%B8%80%E4%B8%8BJDK1.8%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">讲一下JDK1.8的新特性面试题解析</a><h3 id="Jsp"><a href="#Jsp" class="headerlink" title="Jsp"></a>Jsp</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Jsp/JSP%E4%B8%8ESevlet%E5%8C%BA%E5%88%AB_Jsp%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1_Jsp%E5%9B%9B%E7%A7%8D%E4%BD%9C%E7%94%A8%E5%9F%9F_session%E4%B8%8Ecookie%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">JSP与Sevlet区别_Jsp内置对象_Jsp四种作用域_session与cookie的区别</a><h3 id="JVM"><a href="#JVM" class="headerlink" title="JVM"></a>JVM</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/7%E7%A7%8DJVM%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E7%89%B9%E7%82%B9_%E4%BC%98%E5%8A%A3%E5%8A%BF_%E5%8F%8A%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">7种JVM垃圾收集器特点_优劣势_及使用场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/java%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96_%E6%9C%89%E5%93%AA%E4%BA%9B%E8%A1%A1%E9%87%8F%E6%8C%87%E6%A0%87_%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E4%BB%80%E4%B9%88_.pdf">java性能优化_有哪些衡量指标_需要注意什么_</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/JVM%E5%86%85%E5%AD%98%E8%B0%83%E4%BC%98.pdf">JVM内存调优</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/JVM%E7%9A%844%E7%A7%8D%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95_%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E6%80%BB%E7%BB%93.pdf">JVM的4种垃圾回收算法_垃圾回收机制与总结</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/Jvm%E7%BB%84%E6%88%90%E8%BF%90%E8%A1%8C%E6%97%B6%E5%8C%BA%E5%A0%86%E6%A0%88%E9%98%9F%E5%88%97%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">Jvm组成运行时区堆栈队列的区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/%E6%B7%B1%E5%85%A5%E8%AF%A6%E8%A7%A3JVM%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B%E4%B8%8EJVM%E5%8F%82%E6%95%B0%E8%AF%A6%E7%BB%86%E9%85%8D%E7%BD%AE.pdf">深入详解JVM内存模型与JVM参数详细配置</a><h3 id="Kafka"><a href="#Kafka" class="headerlink" title="Kafka"></a>Kafka</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Kafka/Kafka%E9%9D%A2%E8%AF%95%E9%A2%98Kafka%E9%80%9F%E5%BA%A6%E4%B8%BA%E4%BB%80%E4%B9%88%E5%BF%AB.pdf">Kafka面试题Kafka速度为什么快</a><h3 id="Lambda"><a href="#Lambda" class="headerlink" title="Lambda"></a>Lambda</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Lambda/Java8_Lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F.pdf">Java8_Lambda表达式</a><h3 id="leetcode"><a href="#leetcode" class="headerlink" title="leetcode"></a>leetcode</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/leetcode/%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E6%8D%A2%E6%95%B4%E6%95%B0.pdf">字符串转换整数</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/leetcode/%E6%95%B0%E7%BB%84%E4%B8%AD%E5%87%BA%E7%8E%B0%E6%AC%A1%E6%95%B0%E8%B6%85%E8%BF%87%E4%B8%80%E5%8D%8A%E7%9A%84%E6%95%B0%E5%AD%97.pdf">数组中出现次数超过一半的数字</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/leetcode/%E7%94%A8%E4%B8%A4%E4%B8%AA%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97.pdf">用两个栈实现队列</a><h3 id="load-balance"><a href="#load-balance" class="headerlink" title="load_balance"></a>load_balance</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/load_balance/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%9A%84%E5%8E%9F%E7%90%86_%E5%88%86%E7%B1%BB_%E5%AE%9E%E7%8E%B0%E6%9E%B6%E6%9E%84_%E4%BB%A5%E5%8F%8A%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">负载均衡的原理_分类_实现架构_以及使用场景</a><h3 id="MyBatis"><a href="#MyBatis" class="headerlink" title="MyBatis"></a>MyBatis</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/Mybatis%E4%B8%8EHibernate%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">Mybatis与Hibernate的区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/MyBatis%E4%B8%ADMapper%E6%8E%A5%E5%8F%A3%E7%9B%B8%E5%85%B3%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">MyBatis中Mapper接口相关面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/MyBatis%E5%8A%A8%E6%80%81sql%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">MyBatis动态sql面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/Mybatis%E5%BB%B6%E8%BF%9F%E5%8A%A0%E8%BD%BD.pdf">Mybatis延迟加载</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/MyBatis%E7%9A%84%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E5%92%8C%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98.pdf">MyBatis的一级缓存和二级缓存</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/%E4%BD%A0%E7%9F%A5%E9%81%93MyBatis%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%E4%B9%8B%E5%88%9D%E5%A7%8B%E5%8C%96%E6%98%AF%E5%A6%82%E4%BD%95%E6%89%A7%E8%A1%8C%E7%9A%84%E5%90%97.pdf">你知道MyBatis执行过程之初始化是如何执行的吗</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/%E5%AF%B9MybatisPlugin%E7%9A%84%E4%BA%86%E8%A7%A3.pdf">对MybatisPlugin的了解</a><h3 id="MySQL-adv"><a href="#MySQL-adv" class="headerlink" title="MySQL_adv"></a>MySQL_adv</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MySQL_adv/mysql_B+%E6%A0%91%E7%B4%A2%E5%BC%95%E5%92%8C%E5%93%88%E5%B8%8C%E7%B4%A2%E5%BC%95%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">mysql_B+树索引和哈希索引的区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MySQL_adv/MySQL%E4%BA%8B%E5%8A%A1%E4%B8%8EMVCC%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E7%9A%84%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB.pdf">MySQL事务与MVCC如何实现的隔离级别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MySQL_adv/%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8+%E5%8A%A8%E6%80%81%E6%95%B0%E6%8D%AE%E6%BA%90+%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB.pdf">如何实现分库分表+动态数据源+读写分离</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MySQL_adv/%E8%AE%BE%E8%AE%A1%E9%AB%98%E5%B9%B6%E5%8F%91%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%97%B6%E5%80%99_%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B1%82%E9%9D%A2%E8%AF%A5%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1.pdf">设计高并发系统的时候_数据库层面该如何设计</a><h3 id="Mysql-base"><a href="#Mysql-base" class="headerlink" title="Mysql_base"></a>Mysql_base</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Mysql_base/%E5%85%B3%E4%BA%8Emysql%E7%9A%84%E4%B8%89%E8%8C%83%E5%BC%8F_ACID_%E7%B4%A2%E5%BC%95%E7%9A%84%E5%AE%9E%E7%8E%B0.pdf">关于mysql的三范式_ACID_索引的实现</a><h3 id="net"><a href="#net" class="headerlink" title="net"></a>net</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/net/TCP&UDP%E5%8C%BA%E5%88%AB_TCP%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E7%9B%AE%E7%9A%84_OSI%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8B_get%E5%92%8Cpost%E5%8C%BA%E5%88%AB.pdf">TCP&amp;UDP区别_TCP三次握手目的_OSI七层模型_get和post区别</a><h3 id="Netty"><a href="#Netty" class="headerlink" title="Netty"></a>Netty</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Netty/Netty%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86_%E7%89%B9%E7%82%B9%E4%B8%8E%E4%BC%98%E5%8A%BF_%E4%BB%A5%E5%8F%8A%E9%80%82%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">Netty的实现原理_特点与优势_以及适用场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Netty/NIO_BIO_AIO%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">NIO_BIO_AIO的区别</a><h3 id="Nginx"><a href="#Nginx" class="headerlink" title="Nginx"></a>Nginx</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Nginx/%E8%81%8A%E8%81%8A%E4%BD%A0%E5%AF%B9NGINX%E7%9A%84%E7%90%86%E8%A7%A3.pdf">聊聊你对NGINX的理解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Nginx/%E8%AF%B4%E4%B8%80%E4%B8%8B%E4%BD%A0%E5%AF%B9Nginx%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E4%B8%8E%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E7%90%86%E8%A7%A3.pdf">说一下你对Nginx正向代理与反向代理理解</a><h3 id="parallel-programming"><a href="#parallel-programming" class="headerlink" title="parallel_programming"></a>parallel_programming</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/4%E7%A7%8D%E5%B8%B8%E7%94%A8Java%E7%BA%BF%E7%A8%8B%E9%94%81%E7%9A%84%E7%89%B9%E7%82%B9_%E6%80%A7%E8%83%BD%E6%AF%94%E8%BE%83_%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">4种常用Java线程锁的特点_性能比较_使用场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/Java%E6%8F%90%E4%BE%9B%E4%BA%86%E5%93%AA%E5%87%A0%E7%A7%8D%E7%BA%BF%E7%A8%8B%E6%B1%A0_%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">Java提供了哪几种线程池_面试题</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/ThreadLocal%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E7%9A%84%E5%8E%9F%E5%9B%A0%E5%88%86%E6%9E%90%E4%BB%A5%E5%8F%8A%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D.pdf">ThreadLocal的内存泄露的原因分析以及如何避免</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/Volatile%E4%B8%8D%E4%BF%9D%E8%AF%81%E5%8E%9F%E5%AD%90%E6%80%A7%E5%8F%8A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.pdf">Volatile不保证原子性及解决方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/volatile%E5%8F%AF%E8%A7%81%E6%80%A7%E8%AF%A6%E8%A7%A3.pdf">volatile可见性详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/Volatile%E7%A6%81%E6%AD%A2%E6%8C%87%E4%BB%A4%E9%87%8D%E6%8E%92.pdf">Volatile禁止指令重排</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E4%BD%A0%E4%BA%86%E8%A7%A3Java%E5%B9%B6%E5%8F%91%E4%B9%8BAQS.pdf">你了解Java并发之AQS</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E4%BD%A0%E7%9F%A5%E9%81%93Java%E4%B8%AD%E6%9C%89%E5%93%AA%E4%BA%9B%E9%94%81.pdf">你知道Java中有哪些锁</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E4%BD%A0%E7%9F%A5%E9%81%93ReentrantLock%E5%90%97_%E8%B0%88%E4%B8%80%E8%B0%88%E5%AF%B9%E5%AE%83%E7%9A%84%E7%90%86%E8%A7%A3.pdf">你知道ReentrantLock吗_谈一谈对它的理解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%E4%B8%80%E4%B8%AA%E9%AB%98%E5%B9%B6%E5%8F%91%E7%B3%BB%E7%BB%9F.pdf">如何设计一个高并发系统</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E5%B9%B6%E5%8F%91%E5%AE%B9%E5%99%A8%E7%9A%84%E5%8E%9F%E7%90%86.pdf">并发容器的原理</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%81%8A%E4%B8%80%E8%81%8AJava%E5%B9%B6%E5%8F%91%E4%B9%8BSynchronized.pdf">让我们聊一聊Java并发之Synchronized</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E8%B0%88%E4%B8%80%E8%B0%88%E5%B9%B6%E5%8F%91CAS_CompareAndSwap%E5%AE%9E%E7%8E%B0.pdf">谈一谈并发CAS_CompareAndSwap实现</a><h3 id="RabbitMQ"><a href="#RabbitMQ" class="headerlink" title="RabbitMQ"></a>RabbitMQ</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/RabbitMq%E9%98%B2%E6%AD%A2%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">RabbitMq防止消息丢失面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/Rabbit%E6%80%8E%E4%B9%88%E5%AF%B9%E6%B6%88%E6%81%AF%E7%A1%AE%E8%AE%A4%E6%9C%BA%E5%88%B6%E7%9A%84.pdf">Rabbit怎么对消息确认机制的</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%BF%E7%94%A8%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97.pdf">为什么使用消息队列</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/%E4%BB%80%E4%B9%88%E6%98%AF%E6%B5%81%E9%87%8F%E5%89%8A%E5%B3%B0_%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%E7%A7%92%E6%9D%80%E4%B8%9A%E5%8A%A1%E7%9A%84%E5%89%8A%E5%B3%B0%E5%9C%BA%E6%99%AF.pdf">什么是流量削峰_如何解决秒杀业务的削峰场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E6%B6%88%E6%81%AF%E7%9A%84%E9%A1%BA%E5%BA%8F%E6%80%A7.pdf">如何保证消息的顺序性</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%9A%84%E9%AB%98%E5%8F%AF%E7%94%A8.pdf">如何保证消息队列的高可用</a><h3 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis_RDB%E6%8C%81%E4%B9%85%E5%8C%96_AOF%E6%8C%81%E4%B9%85%E5%8C%96.pdf">Redis_RDB持久化_AOF持久化</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E5%8D%95%E7%BA%BF%E7%A8%8B_%E5%8F%8A%E9%AB%98%E5%B9%B6%E5%8F%91%E5%BF%AB%E7%9A%84%E5%8E%9F%E5%9B%A0.pdf">Redis为什么是单线程_及高并发快的原因</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E5%93%A8%E5%85%B5_%E5%A4%8D%E5%88%B6_%E9%9B%86%E7%BE%A4%E7%9A%84%E8%AE%BE%E8%AE%A1%E5%8E%9F%E7%90%86_%E4%BB%A5%E5%8F%8A%E5%8C%BA%E5%88%AB.pdf">Redis哨兵_复制_集群的设计原理_以及区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E5%B9%B6%E5%8F%91%E7%AB%9E%E4%BA%89key%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%E8%AF%A6%E8%A7%A3.pdf">Redis并发竞争key的解决方案详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E7%BC%93%E5%AD%98%E5%92%8CMySQL%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.pdf">Redis缓存和MySQL数据一致性的解决方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F_%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF_%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">Redis缓存穿透_缓存击穿_缓存雪崩面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">Redis缓存雪崩面试题</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">缓存击穿面试题</a><h3 id="ReentrantReadWriteLock"><a href="#ReentrantReadWriteLock" class="headerlink" title="ReentrantReadWriteLock"></a>ReentrantReadWriteLock</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ReentrantReadWriteLock/ReentrantReadWriteLock%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E4%B8%8E%E9%94%81%E8%8E%B7%E5%8F%96.pdf">ReentrantReadWriteLock的实现原理与锁获取</a><h3 id="RocketMQ"><a href="#RocketMQ" class="headerlink" title="RocketMQ"></a>RocketMQ</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RocketMQ/RocketMQ%E7%9A%84%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1_%E5%85%B3%E9%94%AE%E7%89%B9%E6%80%A7%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">RocketMQ的架构设计_关键特性与应用场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RocketMQ/%E5%A6%82%E4%BD%95%E4%BB%8E0%E5%88%B01%E8%AE%BE%E8%AE%A1%E4%B8%80%E4%B8%AA%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E4%B8%AD%E9%97%B4%E4%BB%B6.pdf">如何从0到1设计一个消息队列中间件</a><h3 id="single-login"><a href="#single-login" class="headerlink" title="single_login"></a>single_login</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/single_login/%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95%E9%97%AE%E9%A2%98.pdf">单点登录问题</a><h3 id="Spring"><a href="#Spring" class="headerlink" title="Spring"></a>Spring</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/BeanFactory%E5%92%8CFactoryBean%E7%9A%84%E5%8C%BA%E5%88%AB%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">BeanFactory和FactoryBean的区别面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/Spring%E4%B8%ADbean%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8E%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.pdf">Spring中bean的作用域与生命周期</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/Spring%E4%B8%AD%E4%BD%BF%E7%94%A8%E4%BA%86%E5%93%AA%E4%BA%9B%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.pdf">Spring中使用了哪些设计模式</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/Spring%E4%BA%8B%E5%8A%A1%E7%9A%84%E4%BC%A0%E6%92%AD%E5%B1%9E%E6%80%A7%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">Spring事务的传播属性面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/%E8%AE%B2%E4%B8%80%E8%AE%B2Springbean%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.pdf">讲一讲Springbean的生命周期</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/%E8%AE%B2%E4%B8%80%E8%AE%B2Spring%E5%BE%AA%E7%8E%AF%E4%BE%9D%E8%B5%96%E5%8F%8A%E8%A7%A3%E5%86%B3%E6%96%B9%E5%BC%8F.pdf">讲一讲Spring循环依赖及解决方式</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/%E8%B0%88%E8%B0%88%E5%AF%B9SpringAOP%E7%9A%84%E7%90%86%E8%A7%A3.pdf">谈谈对SpringAOP的理解</a><h3 id="springboot"><a href="#springboot" class="headerlink" title="springboot"></a>springboot</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/springboot/springboot%E5%A6%82%E4%BD%95%E8%AE%BE%E7%BD%AE%E5%90%AF%E5%8A%A8%E6%97%B6%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E6%95%B0%E6%8D%AE.pdf">springboot如何设置启动时的初始化数据</a><h3 id="SpringCloud"><a href="#SpringCloud" class="headerlink" title="SpringCloud"></a>SpringCloud</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/Dubbo%E4%B8%8ESpringCloud%E7%9A%84Ribbon_Hystrix_Feign%E7%9A%84%E4%BC%98%E5%8A%A3%E5%8A%BF%E6%AF%94%E8%BE%83.pdf">Dubbo与SpringCloud的Ribbon_Hystrix_Feign的优劣势比较</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/nacos%E6%9D%83%E9%99%90%E6%8E%A7%E5%88%B6%E6%96%B9%E6%A1%88.pdf">nacos权限控制方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/Restful_SOAP_RPC_SOA_%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">Restful_SOAP_RPC_SOA_微服务之间的区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/SpringCloud%E4%B8%8EDubbo%E7%9A%84%E5%AF%B9%E6%AF%94.pdf">SpringCloud与Dubbo的对比</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/SpringCloud%E7%9A%84%E6%A0%B8%E5%BF%83%E6%88%90%E5%91%98_%E4%BB%A5%E5%8F%8A%E6%9E%B6%E6%9E%84%E5%AE%9E%E7%8E%B0%E8%AF%A6%E7%BB%86%E4%BB%8B%E7%BB%8D.pdf">SpringCloud的核心成员_以及架构实现详细介绍</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E4%B8%8Efeign%E8%B6%85%E6%97%B6%E7%9A%84%E7%BA%A0%E8%91%9B_%E8%AF%A5%E5%92%8B%E4%BC%98%E5%8C%96_.pdf">定时任务与feign超时的纠葛_该咋优化_</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/%E5%BE%AE%E6%9C%8D%E5%8A%A1Dubbo%E5%92%8CSpringCloud%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1_%E4%BC%98%E5%8A%A3%E5%8A%BF%E6%AF%94%E8%BE%83.pdf">微服务Dubbo和SpringCloud架构设计_优劣势比较</a></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> index </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>SpringBoot解决方案</title>
      <link href="java/springboot/collection-solve/"/>
      <url>java/springboot/collection-solve/</url>
      
        <content type="html"><![CDATA[<h1 id="配置文件优先级"><a href="#配置文件优先级" class="headerlink" title="配置文件优先级"></a>配置文件优先级</h1><h2 id="1-项目内部配置文件"><a href="#1-项目内部配置文件" class="headerlink" title="1. 项目内部配置文件"></a>1. 项目内部配置文件</h2><p>spring boot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">　　–file:.&#x2F;config&#x2F;</span><br><span class="line">　　–file:.&#x2F;</span><br><span class="line">　　–classpath:&#x2F;config&#x2F;</span><br><span class="line">　　–classpath:&#x2F;</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="928953-20190613113659461-117207878.png" alt="img"></p><p>以上是按照优先级从高到低的顺序，所有位置的文件都会被加载，高优先级配置内容会覆盖低优先级配置内容。</p><p>SpringBoot会从这四个位置全部加载主配置文件，如果高优先级中配置文件属性与低优先级配置文件不冲突的属性，则会共同存在—互补配置。</p><hr><p>我们也可以通过配置spring.config.location来改变默认配置。</p><p>java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar –spring.config.location=file:///D:/application.properties,classpath:/,<a href="http://classpath/config/">classpath:/config/</a><br>项目打包好以后，我们可以使用命令行参数的形式，启动项目的时候来指定配置文件的新位置。</p><p>指定配置文件和默认加载的这些配置文件共同起作用形成互补配置。<br>Idea 单测启用自定义配置：添加jvm参数：-Dspring.config.location=file:///D:/project_conf/application.yml -ea</p><h2 id="2-外部配置加载顺序"><a href="#2-外部配置加载顺序" class="headerlink" title="2. 外部配置加载顺序"></a>2. 外部配置加载顺序</h2><p>SpringBoot也可以从以下位置加载配置：优先级从高到低；高优先级的配置覆盖低优先级的配置，所有的配置会形成互补配置。</p><p>1.命令行参数</p><ul><li>所有的配置都可以在命令行上进行指定；</li><li>多个配置用空格分开； –配置项=值</li></ul><p>　　java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar –server.port=8087 –server.context-path=/abc</p><p>2.来自java:comp/env的JNDI属性 </p><p>3.Java系统属性（System.getProperties()） </p><p>4.操作系统环境变量 </p><p>5.RandomValuePropertySource配置的random.*属性值</p><p>6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件</p><p>7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件</p><p>8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件</p><p>9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件</p><p>10.@Configuration注解类上的@PropertySource </p><p>11.通过SpringApplication.setDefaultProperties指定的默认属性</p><p><a href="https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#boot-features-external-config">参考官网地址</a></p><p>原文:<a href="https://www.cnblogs.com/erbing/p/11015599.html">SpringBoot配置文件加载位置与优先级</a></p><h1 id="配置文件加密"><a href="#配置文件加密" class="headerlink" title="配置文件加密"></a>配置文件加密</h1><p>Spring-boot项目中properties文件中的密码明文不太安全，</p><p>所以想到给明文加密。了解了一下，有一个依赖工具可以实现这个功能。Ulisesbocchio插件</p><p><em>*<em>*1.*</em>*<em>添加*</em>*<em>maven*</em>*<em>依赖：*</em>*</em></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;com.github.ulisesbocchio&lt;&#x2F;groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;jasypt-spring-boot-starter&lt;&#x2F;artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.14&lt;&#x2F;version&gt;</span><br><span class="line">&lt;&#x2F;dependency&gt;</span><br></pre></td></tr></table></figure><p><em>*<em>*2.*</em>*<em>配置加密密钥或盐值（properties文件中配置）：*</em>*</em></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jasypt.encryptor.password&#x3D;1111111111</span><br></pre></td></tr></table></figure><p><em>*<em>*3.*</em>*<em>进入本地maven库.m2\repository\org\jasypt\jasypt\1.9.2路径下，执行加密命令：*</em>*</em></p><p>java -cp jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=密码明文 password=<em><strong>*1111111111*</strong></em> algorithm=PBEWithMD5AndDES</p><p>执行命令后会出现加密后密码：</p><p><img src= "/img/loading.gif" data-lazy-src="39d11b56889d67e8781c78bdb12643f1365.jpg" alt="39d11b56889d67e8781c78bdb12643f1365.jpg"></p><p><strong>4.将properties文件中需要加密的数据替换成”ENC(密文)”，如：</strong></p><p>user.password=ENC(LtogooCZuLSM2vE8uKcCnA==)</p><p><strong>5.运行代码正常！</strong></p><p>转载于:<a href="https://my.oschina.net/kevin2kelly/blog/2254055">https://my.oschina.net/kevin2kelly/blog/2254055</a></p><p><strong>6. 用于生成加密字符tool类</strong></p><blockquote><p>可以写一个类用来生成</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.travelsky.shopping.console.loca.tool;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.jasypt.util.text.BasicTextEncryptor;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EncryptorGenerator</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">         BasicTextEncryptor textEncryptor = <span class="keyword">new</span> BasicTextEncryptor();</span><br><span class="line">    <span class="comment">// 加密密钥</span></span><br><span class="line">    textEncryptor.setPassword(<span class="string">&quot;1111111111&quot;</span>);</span><br><span class="line">    <span class="comment">// 要加密的数据（如数据库的用户名或密码）</span></span><br><span class="line">    String username = textEncryptor.encrypt(<span class="string">&quot;abc&quot;</span>);</span><br><span class="line">    String password = textEncryptor.encrypt(<span class="string">&quot;123&quot;</span>);</span><br><span class="line">    System.out.println(<span class="string">&quot;username:&quot;</span> + username);</span><br><span class="line">    System.out.println(<span class="string">&quot;password:&quot;</span> + password);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>原文:<a href="https://blog.csdn.net/weixin_34241036/article/details/92575297">使用ulisesbocchio对spring-boot项目properties配置文件信息加密</a></p><hr><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.github.ulisesbocchio<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jasypt-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.github.ulisesbocchio<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jasypt-spring-boot<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.jasypt<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jasypt<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>1.9.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><blockquote><p>问题分析: 因为考虑是内网，我们用的是自己的maven私服，光配置jasypt-spring-boot-starter 无法级联引入，需要单独去引入jasypt-spring-boot的jar </p></blockquote><p>原文链接：<a href="https://blog.csdn.net/moneyshi/article/details/108628693">执笔记忆的空白</a></p><h1 id="创建SpringBoot项目出现Java：程序包org-springframework-stereotype-不存在——解决办法"><a href="#创建SpringBoot项目出现Java：程序包org-springframework-stereotype-不存在——解决办法" class="headerlink" title="创建SpringBoot项目出现Java：程序包org.springframework.stereotype 不存在——解决办法"></a>创建SpringBoot项目出现Java：程序包org.springframework.stereotype 不存在——解决办法</h1><p>前言：在出现问题是查了很多相关的资料，都说的是缺少依赖，需要导包之类的，但是没有说在创建项目后没有选择JRE和Delegate IDE build/run actions to Maven,需要将项目交给Maven管理，希望能对大家有所帮助吧。</p><h2 id="一、问题"><a href="#一、问题" class="headerlink" title="一、问题"></a>一、问题</h2><p><strong>Java：程序包org.springframework.stereotype 不存在</strong></p><p><strong>Java：程序包org.springframework.beans.factory.annotation不存在</strong></p><p><img src= "/img/loading.gif" data-lazy-src="20200714111912938.png" alt="img"></p><h2 id="二、解决方法"><a href="#二、解决方法" class="headerlink" title="二、解决方法"></a>二、解决方法</h2><p>1.File——Settings</p><p><img src= "/img/loading.gif" data-lazy-src="20200714111923702.png" alt="img"></p><p> 2.Setting——Build，Execution，Deployment——Maven——Runner—选择Delegate IDE，选择自己安装的JRE的路径——OK</p><p><img src= "/img/loading.gif" data-lazy-src="20200714111930652.png" alt="img"></p><p>成功启动</p><p><img src= "/img/loading.gif" data-lazy-src="20200714111944812.png" alt="img"></p><p>选好之后运行能成功，因为自己出现好几次这样的问题了，所以记录一下，以免下次出现还不会解决。</p><p>from <a href="https://blog.csdn.net/yyp0304Devin/article/details/107334656">here</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> SpringBoot </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python实现Hexo工具</title>
      <link href="comic/python-hexo-tools/"/>
      <url>comic/python-hexo-tools/</url>
      
        <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>本工具是通过<code>Python</code>脚本实现 <code>Hexo</code> 自动 生成 执行 编译 发布的功能</p><p>你可以在这里<a href="https://victorfengming.gitee.io/file/exe/hexo-tools/hexo-tools-21.4.21.exe">下载exe</a> </p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><h3 id="1-exe下载"><a href="#1-exe下载" class="headerlink" title="1. exe下载"></a>1. exe下载</h3><blockquote><p>将exe文件放在你的任意文件夹中</p></blockquote><h3 id="2-file-md"><a href="#2-file-md" class="headerlink" title="2. file.md"></a>2. file.md</h3><p>创建 名为<code>file.md</code>的文件,在你要写book的目录下</p><blockquote><p>注意: 这里file.md文件名不可更改</p></blockquote><h3 id="3-编辑文件内容"><a href="#3-编辑文件内容" class="headerlink" title="3. 编辑文件内容"></a>3. 编辑文件内容</h3><p>类似这样</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">01<span class="emphasis">_JVM内存与垃概述.md</span></span><br><span class="line"><span class="emphasis">02_</span>如何看术与JVM.md</span><br><span class="line">03<span class="emphasis">_为什学习JVM.md</span></span><br><span class="line"><span class="emphasis">04_</span>面课程特点.md</span><br></pre></td></tr></table></figure><h3 id="4-运行"><a href="#4-运行" class="headerlink" title="4. 运行"></a>4. 运行</h3><h4 id="hexo-tools-21-4-20-exe"><a href="#hexo-tools-21-4-20-exe" class="headerlink" title="hexo-tools-21.4.20.exe"></a>hexo-tools-21.4.20.exe</h4><p><img src= "/img/loading.gif" data-lazy-src="1618599141367.png" alt="1618599141367"></p><h4 id="hexo-tools-21-4-21-exe"><a href="#hexo-tools-21-4-21-exe" class="headerlink" title="hexo-tools-21.4.21.exe"></a>hexo-tools-21.4.21.exe</h4><p><img src= "/img/loading.gif" data-lazy-src="1618654713205.png" alt="1618654713205"></p><h3 id="5-执行"><a href="#5-执行" class="headerlink" title="5. 执行"></a>5. 执行</h3><h4 id="1：生成md"><a href="#1：生成md" class="headerlink" title="1：生成md"></a>1：生成md</h4><p>运行这条选项会根据<code>file.md</code>每行的文本生成对应文件</p><p><img src= "/img/loading.gif" data-lazy-src="1618599290568.png" alt="1618599290568"></p><p>并且在每个文件中自动加入 一级标题</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: &quot;qwfp576&quot;</span><br><span class="line">date:   2021-4-18</span><br><span class="line">cover: &quot;/img/lynk/55.jpg&quot;</span><br><span class="line">author: &quot;victor&quot;</span><br><span class="line">---</span><br><span class="line"></span><br><span class="line"><span class="section"># qwfp576</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="3"><a href="#3" class="headerlink" title="3."></a>3.</h4><p>这步相当于</p><p>在终端直接敲</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">hexo clean</span><br><span class="line">hexo g</span><br><span class="line">hexo s</span><br></pre></td></tr></table></figure><p>编译后,会在当localhost:4000 run</p><h4 id="4-git-指令"><a href="#4-git-指令" class="headerlink" title="4. git 指令"></a>4. git 指令</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add .</span><br><span class="line">git commit -m\&quot;Commit by hexo tool!!!\&quot;</span><br><span class="line">git push</span><br></pre></td></tr></table></figure><p>这里 add &gt;&gt;&gt; all</p><p>commit的信息的固定的</p><p>push时,如果是已经clone下来自己的库,能够直接push</p><p>否则要先登录</p><h4 id="5-gitee-pages"><a href="#5-gitee-pages" class="headerlink" title="5. gitee pages"></a>5. gitee pages</h4><p>gitee pages 部署,这个update</p><p>只有gitee pro 会员才能够 支持自动 更新</p><p>但是这里可以通过py提供了一些代码参考</p><p>先 tag一个 TODO</p><h2 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h2><p>Python: 3.7</p><p>hexo-cli: 4.2.0</p><p>Node.js v15.8.0</p><p><a href="mailto:&#110;&#x70;&#109;&#64;&#x37;&#46;&#x31;&#x30;&#46;&#48;">&#110;&#x70;&#109;&#64;&#x37;&#46;&#x31;&#x30;&#46;&#48;</a></p><p>Pycharm 2021.3</p><p>Pyinstaller</p><p>Gitee Pages</p><h2 id="Hexo-介绍"><a href="#Hexo-介绍" class="headerlink" title="Hexo 介绍"></a>Hexo 介绍</h2><p>一个快速, 简洁且高效的博客框架</p><p>让上百个页面在几秒内瞬间完成渲染. Hexo支持Github Flavored Markdown的所有功能, 甚至可以整合Octopress的大多数插件. 并自己也拥有强大的插件系统.</p><h2 id="实现功能"><a href="#实现功能" class="headerlink" title="实现功能"></a>实现功能</h2><ol><li><p>生成md文件列表,通过读取文件,创建md文件</p></li><li><p>null</p></li><li><p>run 编译 ,html格式以便发布</p></li><li><p>git 自动 push md</p></li><li><p>gitee pages 自动update(dev)</p></li></ol><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><h3 id="cmder"><a href="#cmder" class="headerlink" title="cmder"></a>cmder</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2021/4/17 0:42&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</span><br><span class="line"><span class="keyword">from</span> random <span class="keyword">import</span> randint</span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">version: 21.4.21</span></span><br><span class="line"><span class="string">TODO :         gitee pages auto sync!!!</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="comment"># import sys</span></span><br><span class="line"><span class="comment"># import re</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># dir 是全路径</span></span><br><span class="line"><span class="comment"># 比如: E:\Projects\PycharmProjects\untitled\test\database\redis\2019-09-25-deepin-install-redis.md</span></span><br><span class="line"><span class="comment"># :param dir:</span></span><br><span class="line"><span class="comment"># :return:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HexoTool</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self,pypath</span>):</span></span><br><span class="line">        self.sum_file_name = <span class="string">&quot;file.md&quot;</span></span><br><span class="line">        self.summary_file_name = <span class="string">&quot;SUMMARY.md&quot;</span></span><br><span class="line">        self.readme_name = <span class="string">&quot;README.md&quot;</span></span><br><span class="line">        <span class="comment"># 当前脚本目录</span></span><br><span class="line">        <span class="comment"># self.pypath = sys.path[0]</span></span><br><span class="line">        <span class="comment"># self.pypath = os.getcwd()</span></span><br><span class="line">        <span class="comment"># self.pypath = input(&quot;please input the root path(windows split symbol is \\)\n:&quot;)</span></span><br><span class="line">        self.pypath = pypath</span><br><span class="line">        <span class="comment"># self.root_path = self.pypath</span></span><br><span class="line">        <span class="comment"># sour_path source 源 路径</span></span><br><span class="line">        self.sour_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.sum_file_name</span><br><span class="line">        <span class="comment"># SUMMARY.md 路径</span></span><br><span class="line">        self.summary_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.summary_file_name</span><br><span class="line">        print(<span class="string">&quot;| self.pypath &gt;&gt;&gt; &quot;</span>,self.pypath)</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">repSpilt</span>(<span class="params">self, path</span>):</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        替换路径分隔符</span></span><br><span class="line"><span class="string">        :param path:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        <span class="keyword">return</span> path.replace(<span class="string">&quot;\\&quot;</span>, <span class="string">&quot;\\\\&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">newFile</span>(<span class="params">self, line, dirname</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        创建文件</span></span><br><span class="line"><span class="string">        :param line:</span></span><br><span class="line"><span class="string">        :param dirname:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        print(<span class="string">&quot;| gen file &gt;&gt;&gt;&quot;</span>)</span><br><span class="line">        <span class="comment"># 新建文件的文件名,最后的\n去掉</span></span><br><span class="line">        newName = dirname + <span class="string">&quot;\\&quot;</span> + line[:-<span class="number">1</span>]</span><br><span class="line">        print(<span class="string">&quot;| \t&quot;</span>, line[:-<span class="number">1</span>])</span><br><span class="line">        i = datetime.now()</span><br><span class="line">        ran = randint(<span class="number">1</span>,<span class="number">100</span>)</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(newName, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">            f2.write(<span class="string">&quot;---\n&quot;</span>)</span><br><span class="line">            f2.write(<span class="string">&quot;title: \&quot;&quot;</span> + line[:-<span class="number">4</span>]+<span class="string">&quot;\&quot;\n&quot;</span>)</span><br><span class="line">            f2.write(<span class="string">&quot;date:   %s-%s-%s\n&quot;</span> % (i.year, i.month, i.day))</span><br><span class="line">            f2.write(<span class="string">&quot;cover: \&quot;/img/lynk/&quot;</span>+<span class="built_in">str</span>(ran)+<span class="string">&quot;.jpg\&quot;\n&quot;</span>)</span><br><span class="line">            f2.write(<span class="string">&quot;author: \&quot;victor\&quot;\n&quot;</span>)</span><br><span class="line">            f2.write(<span class="string">&quot;---\n&quot;</span>)</span><br><span class="line">            f2.write(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">            f2.write(<span class="string">&quot;# &quot;</span>+line[:-<span class="number">4</span>]+<span class="string">&quot;\n&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">for_line</span>(<span class="params">self, file</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        读取 sm文件,并遍历行</span></span><br><span class="line"><span class="string">        :param file:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 获取目录</span></span><br><span class="line">        dirname = os.path.dirname(file)</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1:</span><br><span class="line">            i = <span class="number">0</span></span><br><span class="line">            <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line">                <span class="keyword">if</span> line == <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                    <span class="comment"># line 是空行</span></span><br><span class="line">                    <span class="keyword">pass</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="comment"># 判断line是不是最后一行</span></span><br><span class="line">                    <span class="keyword">if</span> line[-<span class="number">1</span>] != <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                        <span class="comment"># 加上换行</span></span><br><span class="line">                        line += <span class="string">&quot;\n&quot;</span></span><br><span class="line"></span><br><span class="line">                    i += <span class="number">1</span></span><br><span class="line">                    self.newFile(line, dirname)</span><br><span class="line"></span><br><span class="line">        print(<span class="string">&quot;| gen &quot;</span>, i, <span class="string">&quot;file success!!!&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| path:&quot;</span>, dirname)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">gen_md</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        生成md文件</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        <span class="comment"># 获取输入</span></span><br><span class="line">        print(<span class="string">&quot;| -----------------------------------------------------&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| md文件生成器&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 通过读取file.md文件中的行数来创建文件&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 生成的文件会和源文件同目录&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 注意:原有文件会被替换&quot;</span>)</span><br><span class="line">        <span class="comment"># print(&quot;| 请输入源目录文件路径,window用 \ 来分隔文件夹&quot;)</span></span><br><span class="line">        <span class="comment"># sourceFile = input(&quot;:&quot;)</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># E:\Projects\PycharmProjects\untitled\newFile</span></span><br><span class="line">        <span class="comment"># sourceFile = self.pypath + &quot;\\&quot; + &quot;SUMMARY.md&quot;</span></span><br><span class="line">        sour_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.sum_file_name</span><br><span class="line">        self.for_line(self.repSpilt(sour_path))</span><br><span class="line">        <span class="comment"># os.system(&#x27;pause&#x27;)</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">hexo_run</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        运行hexo</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        print(<span class="string">&quot;| runing...&quot;</span>)</span><br><span class="line">        os.chdir(self.pypath)</span><br><span class="line">        os.system(<span class="string">&quot;hexo clean&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&quot;hexo g&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&quot;hexo s&quot;</span>)</span><br><span class="line">        <span class="comment"># os.system(&#x27;pause&#x27;)</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">replace_sum</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># SUMMARY.md 路径</span></span><br><span class="line">        <span class="comment"># 更新路径</span></span><br><span class="line">        summary_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.summary_file_name</span><br><span class="line">        sour_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.sum_file_name</span><br><span class="line"></span><br><span class="line">        <span class="comment"># summary_path = self.pypath + &quot;\\&quot; + &quot;SUMMARY.md&quot;</span></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(sour_path, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1, <span class="built_in">open</span>(summary_path, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">            i = <span class="number">0</span></span><br><span class="line">            <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line">                <span class="keyword">if</span> line == <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                    <span class="comment"># line 是空行</span></span><br><span class="line">                    <span class="keyword">pass</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="comment"># 判断line是不是最后一行</span></span><br><span class="line">                    i += <span class="number">1</span></span><br><span class="line">                    <span class="keyword">if</span> line[-<span class="number">1</span>] != <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                        <span class="comment"># 加上换行</span></span><br><span class="line">                        line += <span class="string">&quot;\n&quot;</span></span><br><span class="line">                    f2.write(<span class="string">&quot;- [&quot;</span>)</span><br><span class="line">                    f2.write(line[:-<span class="number">4</span>])</span><br><span class="line">                    f2.write(<span class="string">&quot;](&quot;</span>)</span><br><span class="line">                    f2.write(line[:-<span class="number">1</span>])</span><br><span class="line">                    f2.write(<span class="string">&quot;)&quot;</span>)</span><br><span class="line">                    f2.write(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| gen summary success!!!&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| total effect line:&quot;</span>,i)</span><br><span class="line">        <span class="comment"># os.system(&#x27;pause&#x27;)</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">qucik_git</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        os.chdir(self.pypath)</span><br><span class="line">        os.system(<span class="string">&quot;git add .&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&quot;git commit -m\&quot;Commit by Hexo Tools!!!\&quot;&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&quot;git push&quot;</span>)</span><br><span class="line">        <span class="comment"># os.system(&#x27;pause&#x27;)</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">menu</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 获取输入</span></span><br><span class="line">        <span class="comment"># print(&quot;| =========================================&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| ================ Hexo tools ================&quot;)</span></span><br><span class="line">        print(<span class="string">&quot;| --------------------------- Hexo tools ---------------------------&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 1：生成md&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 2: 转换SUMMARY&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 3: 本地运行&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 4: 发布Git&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 0: exit()&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| --------------------------- Hexo tools ---------------------------&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">input</span>(<span class="string">&quot;| choose operation you need：&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    yt = <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    print(yt)</span><br><span class="line">    print(<span class="string">&quot;| --------------------------- hexo tools ---------------------------&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @version: 21.4.23&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @description: hexo tools auto gen file &amp; build &amp; sync to git&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @author: victor&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @site: https://victorfengming.gitee.io/&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @introduce: https://victorfengming.gitee.io/comic/python-hexo-tools/&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @readme: https://victorfengming.gitee.io/file/exe/hexo-tools/readme.md&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @download: https://victorfengming.gitee.io/file/exe/hexo-tools/hexo-tools-21.4.20.exe&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| --------------------------- hexo tools ---------------------------&quot;</span>)</span><br><span class="line">    <span class="comment"># print(&quot;| 注意：使用前请将exe文件放到file.md同级目录下&quot;)</span></span><br><span class="line">    <span class="comment"># print(&quot;| ========================================&quot;)</span></span><br><span class="line">    <span class="comment"># print(os.path.isfile(&quot;E:\\Projects\\PycharmProjects\\untitled\\newFiletest\\12.md&quot;))</span></span><br><span class="line">    <span class="comment"># ht = HexoTool(input(&quot;please input the root path(windows split symbol is \\)\n:&quot;))</span></span><br><span class="line">    ht = HexoTool(<span class="built_in">input</span>(<span class="string">&quot;please input the root path(windows split symbol is \\)\n:&quot;</span>))</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        cho = ht.menu()</span><br><span class="line">        <span class="keyword">if</span> cho == <span class="string">&quot;1&quot;</span>:</span><br><span class="line">            print(<span class="number">1</span>)</span><br><span class="line">            ht.gen_md()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;2&quot;</span>:</span><br><span class="line">            print(<span class="number">2</span>)</span><br><span class="line">            ht.replace_sum()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;3&quot;</span>:</span><br><span class="line">            print(<span class="number">3</span>)</span><br><span class="line">            ht.hexo_run()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;4&quot;</span>:</span><br><span class="line">            print(<span class="number">4</span>)</span><br><span class="line">            ht.qucik_git()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;0&quot;</span>:</span><br><span class="line">            <span class="comment"># print(&quot;| bye~&quot;)</span></span><br><span class="line">            exit(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 导包</span></span><br><span class="line"><span class="keyword">from</span> tkinter <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> tkinter <span class="keyword">import</span> filedialog, messagebox</span><br><span class="line"><span class="keyword">from</span> hexo_tools <span class="keyword">import</span> HexoTool</span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">| --------------------------- HexoTool tools ---------------------------</span></span><br><span class="line"><span class="string">| @version: 21.4.23</span></span><br><span class="line"><span class="string">| @description: hexo tools auto gen file &amp; build &amp; sync to git</span></span><br><span class="line"><span class="string">| @author: victor</span></span><br><span class="line"><span class="string">| @site: https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="string">| @introduce: https://victorfengming.gitee.io/comic/python-hexo-tools/</span></span><br><span class="line"><span class="string">| @readme: https://victorfengming.gitee.io/file/exe/hexo-tools/readme.md</span></span><br><span class="line"><span class="string">| @download: https://victorfengming.gitee.io/file/exe/hexo-tools/hexo-tools-21.4.21.exe</span></span><br><span class="line"><span class="string">| --------------------------- hexo tools ---------------------------</span></span><br><span class="line"><span class="string">| TODO : </span></span><br><span class="line"><span class="string">|     1. 递归扫描md文件,根据相对路径 生成`SUMMARY.md`</span></span><br><span class="line"><span class="string">|     2. cmd 日志 放入 tk页面 </span></span><br><span class="line"><span class="string">|     5. gitee pages auto update by chrome tools </span></span><br><span class="line"><span class="string">| --------------------------- hexo tools ---------------------------</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Tk_gui</span>():</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, gt</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        初始化魔术方法</span></span><br><span class="line"><span class="string">        用于设置界面的初始状态</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 创建tkinter窗口</span></span><br><span class="line">        self.root = Tk()</span><br><span class="line">        <span class="comment"># 设置窗口的标题</span></span><br><span class="line">        self.root.title(<span class="string">&#x27;Gitbook Tools&#x27;</span>)</span><br><span class="line">        <span class="comment"># 设置窗口的长和宽,最大值和最小值设置相同,用户不可调整窗口大小</span></span><br><span class="line">        self.root.minsize(<span class="number">90</span>, <span class="number">180</span>)</span><br><span class="line">        self.root.maxsize(<span class="number">780</span>, <span class="number">180</span>)</span><br><span class="line">        self.gt = gt</span><br><span class="line">        self.root_path = <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 初始化</span></span><br><span class="line">        <span class="comment"># 初始化主要url</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 调用主要逻辑执行函数</span></span><br><span class="line">        self.main_logic()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">main_logic</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        主业务逻辑</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 顶部信息栏</span></span><br><span class="line">        topp = Frame()</span><br><span class="line">        topp.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 内容栏</span></span><br><span class="line">        self.cont = Frame()</span><br><span class="line">        self.cont.grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 输入选项操作</span></span><br><span class="line">        self.indo = Frame()</span><br><span class="line">        self.indo.grid(row=<span class="number">0</span>, column=<span class="number">1</span>, rowspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 状态栏</span></span><br><span class="line">        self.stat = Frame()</span><br><span class="line">        self.stat.grid(row=<span class="number">2</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># self.get_path()</span></span><br><span class="line">        self.put_button()</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 加入主消息循环</span></span><br><span class="line">        self.root.mainloop()</span><br><span class="line">        <span class="comment"># #</span></span><br><span class="line">        <span class="comment"># self.myStdout()  # 实例化重定向类</span></span><br><span class="line">        <span class="comment"># self.restoreStd()  # 恢复标准输出</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">put_button</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        用于绘制顶部菜单</span></span><br><span class="line"><span class="string">        :param topp:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 菜单栏</span></span><br><span class="line">        <span class="comment"># print(&quot;| 1：生成md&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| 2: 转换SUMMARY&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| 3: 编译&gt;HTML&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| 4: 发布Git&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| 0: exit()&quot;)</span></span><br><span class="line">        self.gen_button(<span class="string">&quot;设置工作路径&quot;</span>, self.get_path).grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line">        self.gen_button(<span class="string">&quot;生成md&quot;</span>, <span class="keyword">lambda</span>: self.button_run_before(gt.gen_md)()).grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># self.gen_button(&quot;转换SUMMARY&quot;, lambda: self.button_run_before(gt.replace_sum)()).grid(row=2, column=0)</span></span><br><span class="line">        self.gen_button(<span class="string">&quot;localhost运行&quot;</span>, <span class="keyword">lambda</span>: self.button_run_before(gt.hexo_run)()).grid(row=<span class="number">3</span>, column=<span class="number">0</span>)</span><br><span class="line">        self.gen_button(<span class="string">&quot;发布Git&quot;</span>, <span class="keyword">lambda</span>: self.button_run_before(gt.qucik_git)()).grid(row=<span class="number">4</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">gen_button</span>(<span class="params">self, text, method</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        生成 button</span></span><br><span class="line"><span class="string">        :param text:</span></span><br><span class="line"><span class="string">        :param method:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="keyword">return</span> Button(self.cont, text=text, command=method, width=<span class="number">22</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_path</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.root_path = filedialog.askdirectory()</span><br><span class="line">        print(<span class="string">&quot;getpath&gt;&gt;&gt;&quot;</span>,self.root_path)</span><br><span class="line">        <span class="comment"># 将路径 从 图形类 传入 工具类</span></span><br><span class="line">        self.gt.pypath = self.root_path</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">button_run_before</span>(<span class="params">self,func</span>):</span></span><br><span class="line">        <span class="comment"># 判断</span></span><br><span class="line">        <span class="comment"># if func != self.get_path and self.root_path == &quot;&quot;:</span></span><br><span class="line">        <span class="keyword">if</span> self.root_path == <span class="string">&quot;&quot;</span>:</span><br><span class="line">            messagebox.showinfo(<span class="string">&#x27;错误&#x27;</span>,<span class="string">&#x27;请先设置工作路径&#x27;</span>)</span><br><span class="line">            self.get_path()</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> func</span><br><span class="line">yt = <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">print(yt)</span><br><span class="line">print(<span class="string">&quot;| --------------------------- hexo tools ---------------------------&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @version: 21.4.21&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @description: hexo tools auto gen file &amp; build &amp; sync to git&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @author: victor&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @site: https://victorfengming.gitee.io/&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @introduce: https://victorfengming.gitee.io/comic/python-hexo-tools/&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @readme: https://victorfengming.gitee.io/file/exe/hexo-tools/readme.md&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @download: https://victorfengming.gitee.io/file/exe/hexo-tools/hexo-tools-21.4.21.exe&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| --------------------------- hexo tools ---------------------------&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 注意：使用前请将exe文件放到file.md同级目录下&quot;</span>)</span><br><span class="line"><span class="comment"># print(&quot;| ========================================&quot;)</span></span><br><span class="line"><span class="comment"># print(os.path.isfile(&quot;E:\\Projects\\PycharmProjects\\untitled\\newFiletest\\12.md&quot;))</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># gt = GitbookTool(input(&quot;please input the root path(windows split symbol is \\)\n:&quot;))</span></span><br><span class="line"></span><br><span class="line">gt = HexoTool(<span class="string">&quot;&quot;</span>)</span><br><span class="line"></span><br><span class="line">t = Tk_gui(gt)</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> Python </tag>
            
            <tag> hexo </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python实现GitBook工具</title>
      <link href="comic/python-gitbook-tools/"/>
      <url>comic/python-gitbook-tools/</url>
      
        <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>本工具是通过<code>Python</code>脚本实现 <code>GitBook</code> 自动 生成 执行 编译 发布的功能</p><p>你可以在这里<a href="https://victorfengming.gitee.io/file/exe/gitbook-tools/gitbook-tools-21.4.23.exe">下载exe</a> </p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><h3 id="1-exe下载-并移动位置"><a href="#1-exe下载-并移动位置" class="headerlink" title="1. exe下载,并移动位置"></a>1. exe下载,并移动位置</h3><blockquote><p>将exe文件放在你的任意文件夹中</p></blockquote><h3 id="2-file-md"><a href="#2-file-md" class="headerlink" title="2. file.md"></a>2. file.md</h3><p>创建 名为<code>file.md</code>的文件,在你要写book的目录下</p><blockquote><p>注意: 这里file.md文件名不可更改</p></blockquote><h3 id="3-编辑文件内容"><a href="#3-编辑文件内容" class="headerlink" title="3. 编辑文件内容"></a>3. 编辑文件内容</h3><p>类似这样</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">01<span class="emphasis">_JVM内存与垃概述.md</span></span><br><span class="line"><span class="emphasis">02_</span>如何看术与JVM.md</span><br><span class="line">03<span class="emphasis">_为什学习JVM.md</span></span><br><span class="line"><span class="emphasis">04_</span>面课程特点.md</span><br></pre></td></tr></table></figure><h3 id="4-运行"><a href="#4-运行" class="headerlink" title="4. 运行"></a>4. 运行</h3><h4 id="gitbook-tools-21-4-18-exe"><a href="#gitbook-tools-21-4-18-exe" class="headerlink" title="gitbook-tools-21.4.18.exe"></a>gitbook-tools-21.4.18.exe</h4><p><img src= "/img/loading.gif" data-lazy-src="1618599141367.png" alt="1618599141367"></p><h4 id="gitbook-tools-21-4-23-exe"><a href="#gitbook-tools-21-4-23-exe" class="headerlink" title="gitbook-tools-21.4.23.exe"></a>gitbook-tools-21.4.23.exe</h4><p><img src= "/img/loading.gif" data-lazy-src="1618654713205.png" alt="1618654713205"></p><h3 id="5-执行"><a href="#5-执行" class="headerlink" title="5. 执行"></a>5. 执行</h3><h4 id="1：生成md"><a href="#1：生成md" class="headerlink" title="1：生成md"></a>1：生成md</h4><p>运行这条选项会根据<code>file.md</code>每行的文本生成对应文件</p><p><img src= "/img/loading.gif" data-lazy-src="1618599290568.png" alt="1618599290568"></p><p>并且在每个文件中自动加入 一级标题</p><p><img src= "/img/loading.gif" data-lazy-src="1618599404144.png" alt="1618599404144"></p><p>现在就可以编写主要内容了</p><h4 id="2-转换SUMMARY"><a href="#2-转换SUMMARY" class="headerlink" title="2: 转换SUMMARY"></a>2: 转换SUMMARY</h4><p>执行这条命令会根据<code>file.md</code>每行的文本生成</p><p>目录格式的 <code>SUMMARY.md</code></p><p>生成后的文件如下</p><p><img src= "/img/loading.gif" data-lazy-src="1618599578828.png" alt="1618599578828"></p><p>如果你可以自己写SUMMARY，这步可以忽略</p><h4 id="3-编译build"><a href="#3-编译build" class="headerlink" title="3. 编译build"></a>3. 编译build</h4><p>这步相当于</p><p>在终端直接敲</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitbook build</span><br></pre></td></tr></table></figure><p>不同的是,如果你没有README文件,会自动创建</p><p><img src= "/img/loading.gif" data-lazy-src="1618599701544.png" alt="1618599701544"></p><p>编译后,会在当前目录生成<code>_book</code><br>文件夹,里面为编译后的HTML,可供发布或部署</p><h4 id="4-git-指令"><a href="#4-git-指令" class="headerlink" title="4. git 指令"></a>4. git 指令</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add _book</span><br><span class="line">git commit -m\&quot;Commit by gitbook tool!!!\&quot;</span><br><span class="line">git push</span><br></pre></td></tr></table></figure><p>这里 add 只是add了 _book 文件夹</p><p>commit的信息的固定的</p><p>push时,如果是已经clone下来自己的库,能够直接push</p><p>否则要先登录</p><h4 id="5-gitee-pages"><a href="#5-gitee-pages" class="headerlink" title="5. gitee pages"></a>5. gitee pages</h4><p>gitee pages 部署,这个update</p><p>只有gitee pro 会员才能够 支持自动 更新</p><p>但是这里可以通过py提供了一些代码参考</p><p>先 tag一个 TODO</p><h2 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h2><p>Python: 3.7 </p><p>GitBook CLI version: 2.3.2</p><p>GitBook version: 3.2.3</p><p>Node.js v15.8.0</p><p><a href="mailto:&#x6e;&#x70;&#109;&#x40;&#x37;&#46;&#x31;&#48;&#x2e;&#48;">&#x6e;&#x70;&#109;&#x40;&#x37;&#46;&#x31;&#48;&#x2e;&#48;</a></p><p>Pycharm 2021.3</p><p>Pyinstaller</p><p>Gitee Pages</p><h2 id="Gitbook-介绍"><a href="#Gitbook-介绍" class="headerlink" title="Gitbook 介绍"></a>Gitbook 介绍</h2><p>GitBook 是一个基于 Node.js 的命令行工具，可使用 Github/Git 和 Markdown 来制作精美的电子书，GitBook 并非关于 Git 的教程。</p><p><a href="https://www.jianshu.com/p/0388d8bb49a7">Gitbook教程</a></p><p>安装遇到的<a href="https://victorfengming.gitee.io/git/gitbook/">问题</a></p><h2 id="实现功能"><a href="#实现功能" class="headerlink" title="实现功能"></a>实现功能</h2><ol><li><p>生成md文件列表,通过读取文件,创建md文件</p></li><li><p>生成SUMMARY.md 替换文件名 为 Gitbook的SUMMARY格式</p></li><li><p>build 编译gitbook ,html格式以便发布</p></li><li><p>git 自动 push <code>_book</code>文件夹</p></li><li><p>gitee pages 自动update(dev)</p></li></ol><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2021/4/17 0:42&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">version: 21.4.18</span></span><br><span class="line"><span class="string">TODO :         gitee pages auto sync!!!</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="comment"># import sys</span></span><br><span class="line"><span class="comment"># import re</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># dir 是全路径</span></span><br><span class="line"><span class="comment"># 比如: E:\Projects\PycharmProjects\untitled\test\database\redis\2019-09-25-deepin-install-redis.md</span></span><br><span class="line"><span class="comment"># :param dir:</span></span><br><span class="line"><span class="comment"># :return:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GitbookTool</span>:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">self.sum_file_name = <span class="string">&quot;file.md&quot;</span></span><br><span class="line"><span class="comment"># 当前脚本目录</span></span><br><span class="line"><span class="comment"># self.pypath = sys.path[0]</span></span><br><span class="line"><span class="comment"># self.pypath = os.getcwd()</span></span><br><span class="line">self.pypath = <span class="built_in">input</span>(<span class="string">&quot;please input the root path(windows split symbol is \\)\n:&quot;</span>)</span><br><span class="line"><span class="comment"># self.root_path = self.pypath</span></span><br><span class="line"><span class="comment"># sour_path source 源 路径</span></span><br><span class="line">self.sour_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.sum_file_name</span><br><span class="line"><span class="comment"># SUMMARY.md 路径</span></span><br><span class="line">self.summary_path = self.pypath + <span class="string">&quot;\\&quot;</span> + <span class="string">&quot;SUMMARY.md&quot;</span></span><br><span class="line">print(<span class="string">&quot;| self.pypath &gt;&gt;&gt; &quot;</span>,self.pypath)</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">repSpilt</span>(<span class="params">self, path</span>):</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        替换路径分隔符</span></span><br><span class="line"><span class="string">        :param path:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line"><span class="keyword">return</span> path.replace(<span class="string">&quot;\\&quot;</span>, <span class="string">&quot;\\\\&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">newFile</span>(<span class="params">self, line, dirname</span>):</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        创建文件</span></span><br><span class="line"><span class="string">        :param line:</span></span><br><span class="line"><span class="string">        :param dirname:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">print(<span class="string">&quot;| gen file &gt;&gt;&gt;&quot;</span>)</span><br><span class="line"><span class="comment"># 新建文件的文件名,最后的\n去掉</span></span><br><span class="line">newName = dirname + <span class="string">&quot;\\&quot;</span> + line[:-<span class="number">1</span>]</span><br><span class="line">print(<span class="string">&quot;| \t&quot;</span>, line[:-<span class="number">1</span>])</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(newName, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">f2.write(<span class="string">&quot;# &quot;</span> + line[:-<span class="number">4</span>])</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">for_line</span>(<span class="params">self, file</span>):</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        读取 sm文件,并遍历行</span></span><br><span class="line"><span class="string">        :param file:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 获取目录</span></span><br><span class="line">dirname = os.path.dirname(file)</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1:</span><br><span class="line">i = <span class="number">0</span></span><br><span class="line"><span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> line == <span class="string">&quot;\n&quot;</span>:</span><br><span class="line"><span class="comment"># line 是空行</span></span><br><span class="line"><span class="keyword">pass</span></span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"><span class="comment"># 判断line是不是最后一行</span></span><br><span class="line"><span class="keyword">if</span> line[-<span class="number">1</span>] != <span class="string">&quot;\n&quot;</span>:</span><br><span class="line"><span class="comment"># 加上换行</span></span><br><span class="line">line += <span class="string">&quot;\n&quot;</span></span><br><span class="line"></span><br><span class="line">i += <span class="number">1</span></span><br><span class="line">self.newFile(line, dirname)</span><br><span class="line"></span><br><span class="line">print(<span class="string">&quot;| gen &quot;</span>, i, <span class="string">&quot;file success!!!&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| path:&quot;</span>, dirname)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">gen_md</span>(<span class="params">self</span>):</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        生成md文件</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line"><span class="comment"># 获取输入</span></span><br><span class="line">print(<span class="string">&quot;| -----------------------------------------------------&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| md文件生成器&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 通过读取file.md文件中的行数来创建文件&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 生成的文件会和源文件同目录&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 注意:原有文件会被替换&quot;</span>)</span><br><span class="line"><span class="comment"># print(&quot;| 请输入源目录文件路径,window用 \ 来分隔文件夹&quot;)</span></span><br><span class="line"><span class="comment"># sourceFile = input(&quot;:&quot;)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># E:\Projects\PycharmProjects\untitled\newFile</span></span><br><span class="line"><span class="comment"># sourceFile = self.pypath + &quot;\\&quot; + &quot;SUMMARY.md&quot;</span></span><br><span class="line">self.for_line(self.repSpilt(self.sour_path))</span><br><span class="line">os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">gitbook_build</span>(<span class="params">self</span>):</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        编译gitbook</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># fname = self.pypath + +&quot;\\&quot;+&quot;SUMMARY.md&quot;</span></span><br><span class="line"><span class="comment"># os.path.isfile(fname)</span></span><br><span class="line">rname = self.pypath + <span class="string">&quot;\\&quot;</span> + <span class="string">&quot;README.md&quot;</span></span><br><span class="line"><span class="comment"># print(&quot;rname &gt;&gt;&gt; &quot;,rname)</span></span><br><span class="line"><span class="keyword">if</span> os.path.isfile(rname):</span><br><span class="line"><span class="comment"># 文件存在</span></span><br><span class="line"><span class="keyword">pass</span></span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(rname, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">f2.write(<span class="string">&quot;This file is generated by py script!!!\n&quot;</span>)</span><br><span class="line">f2.write(<span class="string">&quot;Please write the contents of the README.md&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| building...&quot;</span>)</span><br><span class="line">os.chdir(self.pypath)</span><br><span class="line">os.system(<span class="string">&quot;gitbook build&quot;</span>)</span><br><span class="line">os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">replace_sum</span>(<span class="params">self</span>):</span></span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(self.sour_path, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1, <span class="built_in">open</span>(self.summary_path, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">i = <span class="number">0</span></span><br><span class="line"><span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line"><span class="keyword">if</span> line == <span class="string">&quot;\n&quot;</span>:</span><br><span class="line"><span class="comment"># line 是空行</span></span><br><span class="line"><span class="keyword">pass</span></span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"><span class="comment"># 判断line是不是最后一行</span></span><br><span class="line">i += <span class="number">1</span></span><br><span class="line"><span class="keyword">if</span> line[-<span class="number">1</span>] != <span class="string">&quot;\n&quot;</span>:</span><br><span class="line"><span class="comment"># 加上换行</span></span><br><span class="line">line += <span class="string">&quot;\n&quot;</span></span><br><span class="line">f2.write(<span class="string">&quot;- [&quot;</span>)</span><br><span class="line">f2.write(line[:-<span class="number">4</span>])</span><br><span class="line">f2.write(<span class="string">&quot;](&quot;</span>)</span><br><span class="line">f2.write(line[:-<span class="number">1</span>])</span><br><span class="line">f2.write(<span class="string">&quot;)&quot;</span>)</span><br><span class="line">f2.write(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| gen summary success!!!&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| total effect line:&quot;</span>,i)</span><br><span class="line">os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">qucik_git</span>(<span class="params">self</span>):</span></span><br><span class="line">os.chdir(self.pypath)</span><br><span class="line">os.system(<span class="string">&quot;git add _book&quot;</span>)</span><br><span class="line">os.system(<span class="string">&quot;git commit -m\&quot;Commit by gitbook tool!!!\&quot;&quot;</span>)</span><br><span class="line">os.system(<span class="string">&quot;git push&quot;</span>)</span><br><span class="line">os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">menu</span>(<span class="params">self</span>):</span></span><br><span class="line"><span class="comment"># 获取输入</span></span><br><span class="line"><span class="comment"># print(&quot;| =========================================&quot;)</span></span><br><span class="line"><span class="comment"># print(&quot;| ================ gitbook tools ================&quot;)</span></span><br><span class="line">print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 1：生成md&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 2: 转换SUMMARY&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 3: 编译&gt;HTML&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 4: 发布Git&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 0: exit()&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="built_in">input</span>(<span class="string">&quot;| choose operation you need：&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">yt = <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">print(yt)</span><br><span class="line">print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @version: 21.4.18&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @description: gitbook tools auto gen file &amp; build &amp; sync to git&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @author: victor&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @site: https://victorfengming.gitee.io/&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @introduce: https://victorfengming.gitee.io/comic/python-gitbook-tools/&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @readme: https://victorfengming.gitee.io/file/exe/gitbook-tools/readme.md&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| @download: https://victorfengming.gitee.io/file/exe/gitbook-tools/gitbook-tools-21.4.18.exe&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">print(<span class="string">&quot;| 注意：使用前请将exe文件放到file.md同级目录下&quot;</span>)</span><br><span class="line"><span class="comment"># print(&quot;| ========================================&quot;)</span></span><br><span class="line"><span class="comment"># print(os.path.isfile(&quot;E:\\Projects\\PycharmProjects\\untitled\\newFiletest\\12.md&quot;))</span></span><br><span class="line">gt = GitbookTool()</span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">cho = gt.menu()</span><br><span class="line"><span class="keyword">if</span> cho == <span class="string">&quot;1&quot;</span>:</span><br><span class="line">print(<span class="number">1</span>)</span><br><span class="line">gt.gen_md()</span><br><span class="line"><span class="keyword">elif</span> cho == <span class="string">&quot;2&quot;</span>:</span><br><span class="line">print(<span class="number">2</span>)</span><br><span class="line">gt.replace_sum()</span><br><span class="line"><span class="keyword">elif</span> cho == <span class="string">&quot;3&quot;</span>:</span><br><span class="line">print(<span class="number">3</span>)</span><br><span class="line">gt.gitbook_build()</span><br><span class="line"><span class="keyword">elif</span> cho == <span class="string">&quot;4&quot;</span>:</span><br><span class="line">print(<span class="number">4</span>)</span><br><span class="line">gt.qucik_git()</span><br><span class="line"><span class="keyword">elif</span> cho == <span class="string">&quot;0&quot;</span>:</span><br><span class="line"><span class="comment"># print(&quot;| bye~&quot;)</span></span><br><span class="line">exit(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="gitee-page-代码-dev"><a href="#gitee-page-代码-dev" class="headerlink" title="gitee page 代码(dev)"></a>gitee page 代码(dev)</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> selenium <span class="keyword">import</span> webdriver</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.chrome.options <span class="keyword">import</span> Options</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.common.by <span class="keyword">import</span> By</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.support <span class="keyword">import</span> expected_conditions <span class="keyword">as</span> EC</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.support.ui <span class="keyword">import</span> WebDriverWait <span class="keyword">as</span> Wait</span><br><span class="line"></span><br><span class="line">print(<span class="string">&quot;start refresh gitee pages...&quot;</span>)</span><br><span class="line"></span><br><span class="line">repo_user_name = <span class="string">&quot;victorfengming&quot;</span></span><br><span class="line">repo_name = <span class="string">&quot;shell&quot;</span></span><br><span class="line">login_user = <span class="string">&quot;victorfengming&quot;</span></span><br><span class="line">login_pwd = <span class="string">&quot;xxxx&quot;</span></span><br><span class="line"></span><br><span class="line">url = <span class="string">&quot;https://gitee.com/&quot;</span>+repo_user_name+<span class="string">&quot;/&quot;</span>+repo_name+<span class="string">&quot;/pages&quot;</span></span><br><span class="line"></span><br><span class="line">driver = <span class="string">&quot;E:\\chrome\\chromedriver.exe&quot;</span></span><br><span class="line">chrome_options = Options()</span><br><span class="line">chrome_options.add_argument(<span class="string">&quot;--window-size=1920,1080&quot;</span>)</span><br><span class="line">chrome_options.add_argument(<span class="string">&quot;--start-maximized&quot;</span>)</span><br><span class="line">chrome_options.add_argument(<span class="string">&quot;--headless&quot;</span>)</span><br><span class="line">browser=webdriver.Chrome(executable_path=driver, options=chrome_options)</span><br><span class="line"></span><br><span class="line">browser.get(url)</span><br><span class="line"></span><br><span class="line">Wait(browser, <span class="number">10</span>).until(EC.presence_of_element_located((By.CLASS_NAME, <span class="string">&quot;item.git-nav-user__login-item&quot;</span>)))</span><br><span class="line">print(<span class="string">&quot;load finish. url=&quot;</span> + url)</span><br><span class="line">login_btn = browser.find_element_by_class_name(<span class="string">&quot;item.git-nav-user__login-item&quot;</span>)</span><br><span class="line">login_btn.click()</span><br><span class="line"></span><br><span class="line">Wait(browser, <span class="number">10</span>).until(EC.presence_of_element_located((By.ID, <span class="string">&quot;user_login&quot;</span>)))</span><br><span class="line">Wait(browser, <span class="number">10</span>).until(EC.presence_of_element_located((By.ID, <span class="string">&quot;user_password&quot;</span>)))</span><br><span class="line">print(<span class="string">&quot;login page load finish.&quot;</span>)</span><br><span class="line">user_input = browser.find_element_by_id(<span class="string">&quot;user_login&quot;</span>)</span><br><span class="line">pwd_input = browser.find_element_by_id(<span class="string">&quot;user_password&quot;</span>)</span><br><span class="line">login_btn = browser.find_element_by_name(<span class="string">&quot;commit&quot;</span>)</span><br><span class="line">user_input.send_keys(login_user)</span><br><span class="line">pwd_input.send_keys(login_pwd)</span><br><span class="line">login_btn.click()</span><br><span class="line"></span><br><span class="line">Wait(browser, <span class="number">10</span>).until(EC.presence_of_element_located((By.CLASS_NAME, <span class="string">&quot;button.orange.redeploy-button.ui.update_deploy&quot;</span>)))</span><br><span class="line">print(<span class="string">&quot;login finish.&quot;</span>)</span><br><span class="line">deploy_btn = browser.find_element_by_class_name(<span class="string">&#x27;button.orange.redeploy-button.ui.update_deploy&#x27;</span>)</span><br><span class="line"></span><br><span class="line">browser.execute_script(<span class="string">&quot;window.scrollTo(100, document.body.scrollHeight);&quot;</span>)</span><br><span class="line">deploy_btn.click()</span><br><span class="line">dialog = browser.switch_to.alert</span><br><span class="line">dialog.accept()</span><br><span class="line">print(<span class="string">&quot;refresh gitee pages finish.&quot;</span>)</span><br><span class="line">browser.close()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>参考: <a href="https://www.jianshu.com/p/6460df84a099">https://www.jianshu.com/p/6460df84a099</a></p><p><a href="https://blog.csdn.net/weixin_29981095/article/details/113987875">https://blog.csdn.net/weixin_29981095/article/details/113987875</a></p><h2 id="Pyinstaller"><a href="#Pyinstaller" class="headerlink" title="Pyinstaller"></a>Pyinstaller</h2><p><img src= "/img/loading.gif" data-lazy-src="1618600264685.png" alt="1618600264685"></p><p>设置 运行参数</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-F $FileNameWithoutExtension$.py</span><br></pre></td></tr></table></figure><h2 id="TODO"><a href="#TODO" class="headerlink" title="TODO"></a>TODO</h2><p>gitee pages 自动update(dev)</p><p>tkinter界面</p><h2 id="附录源码"><a href="#附录源码" class="headerlink" title="附录源码"></a>附录源码</h2><h3 id="cmd-版本-fix-bug"><a href="#cmd-版本-fix-bug" class="headerlink" title="cmd 版本 (fix bug)"></a>cmd 版本 (fix bug)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2021/4/17 0:42&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">version: 21.4.18</span></span><br><span class="line"><span class="string">TODO :         gitee pages auto sync!!!</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="comment"># import sys</span></span><br><span class="line"><span class="comment"># import re</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># dir 是全路径</span></span><br><span class="line"><span class="comment"># 比如: E:\Projects\PycharmProjects\untitled\test\database\redis\2019-09-25-deepin-install-redis.md</span></span><br><span class="line"><span class="comment"># :param dir:</span></span><br><span class="line"><span class="comment"># :return:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GitbookTool</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.sum_file_name = <span class="string">&quot;file.md&quot;</span></span><br><span class="line">        <span class="comment"># 当前脚本目录</span></span><br><span class="line">        <span class="comment"># self.pypath = sys.path[0]</span></span><br><span class="line">        <span class="comment"># self.pypath = os.getcwd()</span></span><br><span class="line">        self.pypath = <span class="built_in">input</span>(<span class="string">&quot;please input the root path(windows split symbol is \\)\n:&quot;</span>)</span><br><span class="line">        <span class="comment"># self.root_path = self.pypath</span></span><br><span class="line">        <span class="comment"># sour_path source 源 路径</span></span><br><span class="line">        self.sour_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.sum_file_name</span><br><span class="line">        <span class="comment"># SUMMARY.md 路径</span></span><br><span class="line">        self.summary_path = self.pypath + <span class="string">&quot;\\&quot;</span> + <span class="string">&quot;SUMMARY.md&quot;</span></span><br><span class="line">        print(<span class="string">&quot;| self.pypath &gt;&gt;&gt; &quot;</span>,self.pypath)</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">repSpilt</span>(<span class="params">self, path</span>):</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        替换路径分隔符</span></span><br><span class="line"><span class="string">        :param path:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        <span class="keyword">return</span> path.replace(<span class="string">&quot;\\&quot;</span>, <span class="string">&quot;\\\\&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">newFile</span>(<span class="params">self, line, dirname</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        创建文件</span></span><br><span class="line"><span class="string">        :param line:</span></span><br><span class="line"><span class="string">        :param dirname:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        print(<span class="string">&quot;| gen file &gt;&gt;&gt;&quot;</span>)</span><br><span class="line">        <span class="comment"># 新建文件的文件名,最后的\n去掉</span></span><br><span class="line">        newName = dirname + <span class="string">&quot;\\&quot;</span> + line[:-<span class="number">1</span>]</span><br><span class="line">        print(<span class="string">&quot;| \t&quot;</span>, line[:-<span class="number">1</span>])</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(newName, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">            f2.write(<span class="string">&quot;# &quot;</span> + line[:-<span class="number">4</span>])</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">for_line</span>(<span class="params">self, file</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        读取 sm文件,并遍历行</span></span><br><span class="line"><span class="string">        :param file:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 获取目录</span></span><br><span class="line">        dirname = os.path.dirname(file)</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1:</span><br><span class="line">            i = <span class="number">0</span></span><br><span class="line">            <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> line == <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                    <span class="comment"># line 是空行</span></span><br><span class="line">                    <span class="keyword">pass</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="comment"># 判断line是不是最后一行</span></span><br><span class="line">                    <span class="keyword">if</span> line[-<span class="number">1</span>] != <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                        <span class="comment"># 加上换行</span></span><br><span class="line">                        line += <span class="string">&quot;\n&quot;</span></span><br><span class="line"></span><br><span class="line">                    i += <span class="number">1</span></span><br><span class="line">                    self.newFile(line, dirname)</span><br><span class="line"></span><br><span class="line">        print(<span class="string">&quot;| gen &quot;</span>, i, <span class="string">&quot;file success!!!&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| path:&quot;</span>, dirname)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">gen_md</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        生成md文件</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        <span class="comment"># 获取输入</span></span><br><span class="line">        print(<span class="string">&quot;| -----------------------------------------------------&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| md文件生成器&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 通过读取file.md文件中的行数来创建文件&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 生成的文件会和源文件同目录&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 注意:原有文件会被替换&quot;</span>)</span><br><span class="line">        <span class="comment"># print(&quot;| 请输入源目录文件路径,window用 \ 来分隔文件夹&quot;)</span></span><br><span class="line">        <span class="comment"># sourceFile = input(&quot;:&quot;)</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># E:\Projects\PycharmProjects\untitled\newFile</span></span><br><span class="line">        <span class="comment"># sourceFile = self.pypath + &quot;\\&quot; + &quot;SUMMARY.md&quot;</span></span><br><span class="line">        self.for_line(self.repSpilt(self.sour_path))</span><br><span class="line">        os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">gitbook_build</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        编译gitbook</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># fname = self.pypath + +&quot;\\&quot;+&quot;SUMMARY.md&quot;</span></span><br><span class="line">        <span class="comment"># os.path.isfile(fname)</span></span><br><span class="line">        rname = self.pypath + <span class="string">&quot;\\&quot;</span> + <span class="string">&quot;README.md&quot;</span></span><br><span class="line">        print(<span class="string">&quot;rname &gt;&gt;&gt; &quot;</span>,rname)</span><br><span class="line">        <span class="keyword">if</span> os.path.isfile(rname):</span><br><span class="line">            <span class="comment"># 文件存在</span></span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(rname, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">                f2.write(<span class="string">&quot;This file is generated by py script!!!\n&quot;</span>)</span><br><span class="line">                f2.write(<span class="string">&quot;Please write the contents of the README.md&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># bookignore = self.pypath + +&quot;\\&quot;+&quot;SUMMARY.md&quot;</span></span><br><span class="line">        <span class="comment"># os.path.isfile(fname)</span></span><br><span class="line">        bookignore = self.pypath + <span class="string">&quot;\\&quot;</span> + <span class="string">&quot;.bookignore&quot;</span></span><br><span class="line">        <span class="keyword">if</span> os.path.isfile(bookignore):</span><br><span class="line">            <span class="comment"># 文件存在 啥也不干</span></span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(bookignore, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">                f2.write(<span class="string">&quot;file.md&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        print(<span class="string">&quot;| building...&quot;</span>)</span><br><span class="line">        os.chdir(self.pypath)</span><br><span class="line">        os.system(<span class="string">&quot;gitbook build&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">replace_sum</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(self.sour_path, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1, <span class="built_in">open</span>(self.summary_path, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">            i = <span class="number">0</span></span><br><span class="line">            <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line">                <span class="keyword">if</span> line == <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                    <span class="comment"># line 是空行</span></span><br><span class="line">                    <span class="keyword">pass</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="comment"># 判断line是不是最后一行</span></span><br><span class="line">                    i += <span class="number">1</span></span><br><span class="line">                    <span class="keyword">if</span> line[-<span class="number">1</span>] != <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                        <span class="comment"># 加上换行</span></span><br><span class="line">                        line += <span class="string">&quot;\n&quot;</span></span><br><span class="line">                    f2.write(<span class="string">&quot;- [&quot;</span>)</span><br><span class="line">                    f2.write(line[:-<span class="number">4</span>])</span><br><span class="line">                    f2.write(<span class="string">&quot;](&quot;</span>)</span><br><span class="line">                    f2.write(line[:-<span class="number">1</span>])</span><br><span class="line">                    f2.write(<span class="string">&quot;)&quot;</span>)</span><br><span class="line">                    f2.write(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| gen summary success!!!&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| total effect line:&quot;</span>,i)</span><br><span class="line">        os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">qucik_git</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        os.chdir(self.pypath)</span><br><span class="line">        os.system(<span class="string">&quot;git add _book&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&quot;git commit -m\&quot;Commit by gitbook tool!!!\&quot;&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&quot;git push&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">menu</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 获取输入</span></span><br><span class="line">        <span class="comment"># print(&quot;| =========================================&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| ================ gitbook tools ================&quot;)</span></span><br><span class="line">        print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 1：生成md&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 2: 转换SUMMARY&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 3: 编译&gt;HTML&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 4: 发布Git&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 0: exit()&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">input</span>(<span class="string">&quot;| choose operation you need：&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    yt = <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    print(yt)</span><br><span class="line">    print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @version: 21.4.22&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @description: gitbook tools auto gen file &amp; build &amp; sync to git&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @author: victor&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @site: https://victorfengming.gitee.io/&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @introduce: https://victorfengming.gitee.io/comic/python-gitbook-tools/&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @readme: https://victorfengming.gitee.io/file/exe/gitbook-tools/readme.md&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @download: https://victorfengming.gitee.io/file/exe/gitbook-tools/gitbook-tools-21.4.22.exe&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| 注意：使用前请将exe文件放到file.md同级目录下&quot;</span>)</span><br><span class="line">    <span class="comment"># print(&quot;| ========================================&quot;)</span></span><br><span class="line">    <span class="comment"># print(os.path.isfile(&quot;E:\\Projects\\PycharmProjects\\untitled\\newFiletest\\12.md&quot;))</span></span><br><span class="line">    gt = GitbookTool()</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        cho = gt.menu()</span><br><span class="line">        <span class="keyword">if</span> cho == <span class="string">&quot;1&quot;</span>:</span><br><span class="line">            print(<span class="number">1</span>)</span><br><span class="line">            gt.gen_md()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;2&quot;</span>:</span><br><span class="line">            print(<span class="number">2</span>)</span><br><span class="line">            gt.replace_sum()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;3&quot;</span>:</span><br><span class="line">            print(<span class="number">3</span>)</span><br><span class="line">            gt.gitbook_build()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;4&quot;</span>:</span><br><span class="line">            print(<span class="number">4</span>)</span><br><span class="line">            gt.qucik_git()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;0&quot;</span>:</span><br><span class="line">            <span class="comment"># print(&quot;| bye~&quot;)</span></span><br><span class="line">            exit(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="图形Tk版本"><a href="#图形Tk版本" class="headerlink" title="图形Tk版本"></a>图形Tk版本</h3><h4 id="main-py"><a href="#main-py" class="headerlink" title="main.py"></a>main.py</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 导包</span></span><br><span class="line"><span class="keyword">from</span> tkinter <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> tkinter <span class="keyword">import</span> filedialog, messagebox</span><br><span class="line"><span class="keyword">from</span> gitbook_tools <span class="keyword">import</span> GitbookTool</span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">| --------------------------- gitbook tools ---------------------------</span></span><br><span class="line"><span class="string">| @version: 21.4.23</span></span><br><span class="line"><span class="string">| @description: gitbook tools auto gen file &amp; build &amp; sync to git</span></span><br><span class="line"><span class="string">| @author: victor</span></span><br><span class="line"><span class="string">| @site: https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="string">| @introduce: https://victorfengming.gitee.io/comic/python-gitbook-tools/</span></span><br><span class="line"><span class="string">| @readme: https://victorfengming.gitee.io/file/exe/gitbook-tools/readme.md</span></span><br><span class="line"><span class="string">| @download: https://victorfengming.gitee.io/file/exe/gitbook-tools/gitbook-tools-21.4.23.exe</span></span><br><span class="line"><span class="string">| --------------------------- gitbook tools ---------------------------</span></span><br><span class="line"><span class="string">| TODO : </span></span><br><span class="line"><span class="string">|     1. 递归扫描md文件,根据相对路径 生成`SUMMARY.md`</span></span><br><span class="line"><span class="string">|     2. cmd 日志 放入 tk页面 </span></span><br><span class="line"><span class="string">|     5. gitee pages auto update by chrome tools </span></span><br><span class="line"><span class="string">| --------------------------- gitbook tools ---------------------------</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Tk_gui</span>():</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, gt</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        初始化魔术方法</span></span><br><span class="line"><span class="string">        用于设置界面的初始状态</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 创建tkinter窗口</span></span><br><span class="line">        self.root = Tk()</span><br><span class="line">        <span class="comment"># 设置窗口的标题</span></span><br><span class="line">        self.root.title(<span class="string">&#x27;Gitbook Tools&#x27;</span>)</span><br><span class="line">        <span class="comment"># 设置窗口的长和宽,最大值和最小值设置相同,用户不可调整窗口大小</span></span><br><span class="line">        self.root.minsize(<span class="number">90</span>, <span class="number">180</span>)</span><br><span class="line">        self.root.maxsize(<span class="number">780</span>, <span class="number">180</span>)</span><br><span class="line">        self.gt = gt</span><br><span class="line">        self.root_path = <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 初始化</span></span><br><span class="line">        <span class="comment"># 初始化主要url</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 调用主要逻辑执行函数</span></span><br><span class="line">        self.main_logic()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">main_logic</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        主业务逻辑</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 顶部信息栏</span></span><br><span class="line">        topp = Frame()</span><br><span class="line">        topp.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 内容栏</span></span><br><span class="line">        self.cont = Frame()</span><br><span class="line">        self.cont.grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 输入选项操作</span></span><br><span class="line">        self.indo = Frame()</span><br><span class="line">        self.indo.grid(row=<span class="number">0</span>, column=<span class="number">1</span>, rowspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 状态栏</span></span><br><span class="line">        self.stat = Frame()</span><br><span class="line">        self.stat.grid(row=<span class="number">2</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># self.get_path()</span></span><br><span class="line">        self.put_button()</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 加入主消息循环</span></span><br><span class="line">        self.root.mainloop()</span><br><span class="line">        <span class="comment"># #</span></span><br><span class="line">        <span class="comment"># self.myStdout()  # 实例化重定向类</span></span><br><span class="line">        <span class="comment"># self.restoreStd()  # 恢复标准输出</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">put_button</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        用于绘制顶部菜单</span></span><br><span class="line"><span class="string">        :param topp:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 菜单栏</span></span><br><span class="line">        <span class="comment"># print(&quot;| 1：生成md&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| 2: 转换SUMMARY&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| 3: 编译&gt;HTML&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| 4: 发布Git&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| 0: exit()&quot;)</span></span><br><span class="line">        self.gen_button(<span class="string">&quot;设置工作路径&quot;</span>, self.get_path).grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line">        self.gen_button(<span class="string">&quot;生成md&quot;</span>, <span class="keyword">lambda</span>: self.button_run_before(gt.gen_md)()).grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        self.gen_button(<span class="string">&quot;转换SUMMARY&quot;</span>, <span class="keyword">lambda</span>: self.button_run_before(gt.replace_sum)()).grid(row=<span class="number">2</span>, column=<span class="number">0</span>)</span><br><span class="line">        self.gen_button(<span class="string">&quot;编译&gt;HTML&quot;</span>, <span class="keyword">lambda</span>: self.button_run_before(gt.gitbook_build)()).grid(row=<span class="number">3</span>, column=<span class="number">0</span>)</span><br><span class="line">        self.gen_button(<span class="string">&quot;发布Git&quot;</span>, <span class="keyword">lambda</span>: self.button_run_before(gt.qucik_git)()).grid(row=<span class="number">4</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">gen_button</span>(<span class="params">self, text, method</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        生成 button</span></span><br><span class="line"><span class="string">        :param text:</span></span><br><span class="line"><span class="string">        :param method:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="keyword">return</span> Button(self.cont, text=text, command=method, width=<span class="number">22</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_path</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.root_path = filedialog.askdirectory()</span><br><span class="line">        print(<span class="string">&quot;getpath&gt;&gt;&gt;&quot;</span>,self.root_path)</span><br><span class="line">        <span class="comment"># 将路径 从 图形类 传入 工具类</span></span><br><span class="line">        self.gt.pypath = self.root_path</span><br><span class="line"></span><br><span class="line">    <span class="comment"># cmd 消息 放入 tk页面 （dev）</span></span><br><span class="line">    <span class="comment"># def myStdout(self):  # 重定向类</span></span><br><span class="line">    <span class="comment">#     # 将其备份</span></span><br><span class="line">    <span class="comment">#     self.stdoutbak = sys.stdout</span></span><br><span class="line">    <span class="comment">#     self.stderrbak = sys.stderr</span></span><br><span class="line">    <span class="comment">#     # 重定向</span></span><br><span class="line">    <span class="comment">#     sys.stdout = self</span></span><br><span class="line">    <span class="comment">#     sys.stderr = self</span></span><br><span class="line">    <span class="comment">#</span></span><br><span class="line">    <span class="comment"># def write(self, info):</span></span><br><span class="line">    <span class="comment">#     t = Text(self.cont)  # 创建多行文本控件</span></span><br><span class="line">    <span class="comment">#     t.pack()  # 布局在窗体上</span></span><br><span class="line">    <span class="comment">#     # info信息即标准输出sys.stdout和sys.stderr接收到的输出信息</span></span><br><span class="line">    <span class="comment">#     t.insert(&#x27;end&#x27;, info)  # 在多行文本控件最后一行插入print信息</span></span><br><span class="line">    <span class="comment">#     t.update()  # 更新显示的文本，不加这句插入的信息无法显示</span></span><br><span class="line">    <span class="comment">#     t.see(END)  # 始终显示最后一行，不加这句，当文本溢出控件最后一行时，不会自动显示最后一行</span></span><br><span class="line">    <span class="comment">#</span></span><br><span class="line">    <span class="comment"># def restoreStd(self):</span></span><br><span class="line">    <span class="comment">#     # 恢复标准输出</span></span><br><span class="line">    <span class="comment">#     sys.stdout = self.stdoutbak</span></span><br><span class="line">    <span class="comment">#     sys.stderr = self.stderrbak</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">button_run_before</span>(<span class="params">self,func</span>):</span></span><br><span class="line">        <span class="comment"># 判断</span></span><br><span class="line">        <span class="comment"># if func != self.get_path and self.root_path == &quot;&quot;:</span></span><br><span class="line">        <span class="keyword">if</span> self.root_path == <span class="string">&quot;&quot;</span>:</span><br><span class="line">            messagebox.showinfo(<span class="string">&#x27;错误&#x27;</span>,<span class="string">&#x27;请先设置工作路径&#x27;</span>)</span><br><span class="line">            self.get_path()</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> func</span><br><span class="line"></span><br><span class="line"><span class="comment"># print(&quot;| ========================================&quot;)</span></span><br><span class="line"><span class="comment"># print(os.path.isfile(&quot;E:\\Projects\\PycharmProjects\\untitled\\newFiletest\\12.md&quot;))</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># gt = GitbookTool(input(&quot;please input the root path(windows split symbol is \\)\n:&quot;))</span></span><br><span class="line"></span><br><span class="line">gt = GitbookTool()</span><br><span class="line"></span><br><span class="line">t = Tk_gui(gt)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="gitbook-tools-py"><a href="#gitbook-tools-py" class="headerlink" title="gitbook_tools.py"></a>gitbook_tools.py</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2021/4/17 0:42&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">version: 21.4.18</span></span><br><span class="line"><span class="string">TODO :         gitee pages auto sync!!!</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="comment"># import sys</span></span><br><span class="line"><span class="comment"># import re</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># dir 是全路径</span></span><br><span class="line"><span class="comment"># 比如: E:\Projects\PycharmProjects\untitled\test\database\redis\2019-09-25-deepin-install-redis.md</span></span><br><span class="line"><span class="comment"># :param dir:</span></span><br><span class="line"><span class="comment"># :return:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GitbookTool</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.sum_file_name = <span class="string">&quot;file.md&quot;</span></span><br><span class="line">        self.summary_file_name = <span class="string">&quot;SUMMARY.md&quot;</span></span><br><span class="line">        self.readme_name = <span class="string">&quot;README.md&quot;</span></span><br><span class="line">        <span class="comment"># 当前脚本目录</span></span><br><span class="line">        <span class="comment"># self.pypath = sys.path[0]</span></span><br><span class="line">        <span class="comment"># self.pypath = os.getcwd()</span></span><br><span class="line">        <span class="comment"># self.pypath = input(&quot;please input the root path(windows split symbol is \\)\n:&quot;)</span></span><br><span class="line">        self.pypath = <span class="string">&quot;&quot;</span></span><br><span class="line">        <span class="comment"># self.root_path = self.pypath</span></span><br><span class="line">        <span class="comment"># sour_path source 源 路径</span></span><br><span class="line">        self.sour_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.sum_file_name</span><br><span class="line">        <span class="comment"># SUMMARY.md 路径</span></span><br><span class="line">        self.summary_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.summary_file_name</span><br><span class="line">        print(<span class="string">&quot;| self.pypath &gt;&gt;&gt; &quot;</span>,self.pypath)</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">repSpilt</span>(<span class="params">self, path</span>):</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        替换路径分隔符</span></span><br><span class="line"><span class="string">        :param path:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        <span class="keyword">return</span> path.replace(<span class="string">&quot;\\&quot;</span>, <span class="string">&quot;\\\\&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">newFile</span>(<span class="params">self, line, dirname</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        创建文件</span></span><br><span class="line"><span class="string">        :param line:</span></span><br><span class="line"><span class="string">        :param dirname:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        print(<span class="string">&quot;| gen file &gt;&gt;&gt;&quot;</span>)</span><br><span class="line">        <span class="comment"># 新建文件的文件名,最后的\n去掉</span></span><br><span class="line">        newName = dirname + <span class="string">&quot;\\&quot;</span> + line[:-<span class="number">1</span>]</span><br><span class="line">        print(<span class="string">&quot;| \t&quot;</span>, line[:-<span class="number">1</span>])</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(newName, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">            f2.write(<span class="string">&quot;# &quot;</span> + line[:-<span class="number">4</span>])</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">for_line</span>(<span class="params">self, file</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        读取 sm文件,并遍历行</span></span><br><span class="line"><span class="string">        :param file:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 获取目录</span></span><br><span class="line">        dirname = os.path.dirname(file)</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1:</span><br><span class="line">            i = <span class="number">0</span></span><br><span class="line">            <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line">                <span class="keyword">if</span> line == <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                    <span class="comment"># line 是空行</span></span><br><span class="line">                    <span class="keyword">pass</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="comment"># 判断line是不是最后一行</span></span><br><span class="line">                    <span class="keyword">if</span> line[-<span class="number">1</span>] != <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                        <span class="comment"># 加上换行</span></span><br><span class="line">                        line += <span class="string">&quot;\n&quot;</span></span><br><span class="line"></span><br><span class="line">                    i += <span class="number">1</span></span><br><span class="line">                    self.newFile(line, dirname)</span><br><span class="line"></span><br><span class="line">        print(<span class="string">&quot;| gen &quot;</span>, i, <span class="string">&quot;file success!!!&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| path:&quot;</span>, dirname)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">gen_md</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        生成md文件</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        <span class="comment"># 获取输入</span></span><br><span class="line">        print(<span class="string">&quot;| -----------------------------------------------------&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| md文件生成器&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 通过读取file.md文件中的行数来创建文件&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 生成的文件会和源文件同目录&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 注意:原有文件会被替换&quot;</span>)</span><br><span class="line">        <span class="comment"># print(&quot;| 请输入源目录文件路径,window用 \ 来分隔文件夹&quot;)</span></span><br><span class="line">        <span class="comment"># sourceFile = input(&quot;:&quot;)</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># E:\Projects\PycharmProjects\untitled\newFile</span></span><br><span class="line">        <span class="comment"># sourceFile = self.pypath + &quot;\\&quot; + &quot;SUMMARY.md&quot;</span></span><br><span class="line">        sour_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.sum_file_name</span><br><span class="line">        self.for_line(self.repSpilt(sour_path))</span><br><span class="line">        <span class="comment"># os.system(&#x27;pause&#x27;)</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">gitbook_build</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        编译gitbook</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># fname = self.pypath + +&quot;\\&quot;+&quot;SUMMARY.md&quot;</span></span><br><span class="line">        <span class="comment"># os.path.isfile(fname)</span></span><br><span class="line">        rname = self.pypath + <span class="string">&quot;\\&quot;</span> + self.readme_name</span><br><span class="line">        print(<span class="string">&quot;rname &gt;&gt;&gt; &quot;</span>,rname)</span><br><span class="line">        <span class="keyword">if</span> os.path.isfile(rname):</span><br><span class="line">            <span class="comment"># 文件存在</span></span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(rname, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">                f2.write(<span class="string">&quot;This file is generated by py script!!!\n&quot;</span>)</span><br><span class="line">                f2.write(<span class="string">&quot;Please write the contents of the README.md&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># bookignore = self.pypath + +&quot;\\&quot;+&quot;SUMMARY.md&quot;</span></span><br><span class="line">        <span class="comment"># os.path.isfile(fname)</span></span><br><span class="line">        bookignore = self.pypath + <span class="string">&quot;\\&quot;</span> + <span class="string">&quot;.bookignore&quot;</span></span><br><span class="line">        <span class="keyword">if</span> os.path.isfile(bookignore):</span><br><span class="line">            <span class="comment"># 文件存在 啥也不干</span></span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(bookignore, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">                f2.write(<span class="string">&quot;file.md\n&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        print(<span class="string">&quot;| building...&quot;</span>)</span><br><span class="line">        os.chdir(self.pypath)</span><br><span class="line">        os.system(<span class="string">&quot;gitbook build&quot;</span>)</span><br><span class="line">        <span class="comment"># os.system(&#x27;pause&#x27;)</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">replace_sum</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># SUMMARY.md 路径</span></span><br><span class="line">        <span class="comment"># 更新路径</span></span><br><span class="line">        summary_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.summary_file_name</span><br><span class="line">        sour_path = self.pypath + <span class="string">&quot;\\&quot;</span> + self.sum_file_name</span><br><span class="line"></span><br><span class="line">        <span class="comment"># summary_path = self.pypath + &quot;\\&quot; + &quot;SUMMARY.md&quot;</span></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(sour_path, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1, <span class="built_in">open</span>(summary_path, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">            i = <span class="number">0</span></span><br><span class="line">            <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line">                <span class="keyword">if</span> line == <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                    <span class="comment"># line 是空行</span></span><br><span class="line">                    <span class="keyword">pass</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="comment"># 判断line是不是最后一行</span></span><br><span class="line">                    i += <span class="number">1</span></span><br><span class="line">                    <span class="keyword">if</span> line[-<span class="number">1</span>] != <span class="string">&quot;\n&quot;</span>:</span><br><span class="line">                        <span class="comment"># 加上换行</span></span><br><span class="line">                        line += <span class="string">&quot;\n&quot;</span></span><br><span class="line">                    f2.write(<span class="string">&quot;- [&quot;</span>)</span><br><span class="line">                    f2.write(line[:-<span class="number">4</span>])</span><br><span class="line">                    f2.write(<span class="string">&quot;](&quot;</span>)</span><br><span class="line">                    f2.write(line[:-<span class="number">1</span>])</span><br><span class="line">                    f2.write(<span class="string">&quot;)&quot;</span>)</span><br><span class="line">                    f2.write(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| gen summary success!!!&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| total effect line:&quot;</span>,i)</span><br><span class="line">        <span class="comment"># os.system(&#x27;pause&#x27;)</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">qucik_git</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        os.chdir(self.pypath)</span><br><span class="line">        os.system(<span class="string">&quot;git add _book&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&quot;git commit -m\&quot;Commit by gitbook tool!!!\&quot;&quot;</span>)</span><br><span class="line">        os.system(<span class="string">&quot;git push&quot;</span>)</span><br><span class="line">        <span class="comment"># os.system(&#x27;pause&#x27;)</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">menu</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 获取输入</span></span><br><span class="line">        <span class="comment"># print(&quot;| =========================================&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;| ================ gitbook tools ================&quot;)</span></span><br><span class="line">        print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 1：生成md&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 2: 转换SUMMARY&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 3: 编译&gt;HTML&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 4: 发布Git&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| 0: exit()&quot;</span>)</span><br><span class="line">        print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">input</span>(<span class="string">&quot;| choose operation you need：&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    yt = <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    print(yt)</span><br><span class="line">    print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @version: 21.4.23&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @description: gitbook tools auto gen file &amp; build &amp; sync to git&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @author: victor&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @site: https://victorfengming.gitee.io/&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @introduce: https://victorfengming.gitee.io/comic/python-gitbook-tools/&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @readme: https://victorfengming.gitee.io/file/exe/gitbook-tools/readme.md&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| @download: https://victorfengming.gitee.io/file/exe/gitbook-tools/gitbook-tools-21.4.23.exe&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;| --------------------------- gitbook tools ---------------------------&quot;</span>)</span><br><span class="line">    <span class="comment"># print(&quot;| 注意：使用前请将exe文件放到file.md同级目录下&quot;)</span></span><br><span class="line">    <span class="comment"># print(&quot;| ========================================&quot;)</span></span><br><span class="line">    <span class="comment"># print(os.path.isfile(&quot;E:\\Projects\\PycharmProjects\\untitled\\newFiletest\\12.md&quot;))</span></span><br><span class="line">    gt = GitbookTool(<span class="built_in">input</span>(<span class="string">&quot;please input the root path(windows split symbol is \\)\n:&quot;</span>))</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        cho = gt.menu()</span><br><span class="line">        <span class="keyword">if</span> cho == <span class="string">&quot;1&quot;</span>:</span><br><span class="line">            print(<span class="number">1</span>)</span><br><span class="line">            gt.gen_md()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;2&quot;</span>:</span><br><span class="line">            print(<span class="number">2</span>)</span><br><span class="line">            gt.replace_sum()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;3&quot;</span>:</span><br><span class="line">            print(<span class="number">3</span>)</span><br><span class="line">            gt.gitbook_build()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;4&quot;</span>:</span><br><span class="line">            print(<span class="number">4</span>)</span><br><span class="line">            gt.qucik_git()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&quot;0&quot;</span>:</span><br><span class="line">            <span class="comment"># print(&quot;| bye~&quot;)</span></span><br><span class="line">            exit(<span class="number">0</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> gitbook </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MySQL极客时间45讲</title>
      <link href="database/mysql/geek-45/"/>
      <url>database/mysql/geek-45/</url>
      
        <content type="html"><![CDATA[<h1 id="01-基础架构：一条SQL查询语句是如何执行的"><a href="#01-基础架构：一条SQL查询语句是如何执行的" class="headerlink" title="01.基础架构：一条SQL查询语句是如何执行的?"></a>01.基础架构：一条SQL查询语句是如何执行的?</h1><h1 id="02-日志系统：一条SQL更新语句是如何执行的"><a href="#02-日志系统：一条SQL更新语句是如何执行的" class="headerlink" title="02.日志系统：一条SQL更新语句是如何执行的?"></a>02.日志系统：一条SQL更新语句是如何执行的?</h1><h1 id="03-事务隔离：为什么你改了我还看不见"><a href="#03-事务隔离：为什么你改了我还看不见" class="headerlink" title="03.事务隔离：为什么你改了我还看不见?"></a>03.事务隔离：为什么你改了我还看不见?</h1><h1 id="04-深入浅出索引-上"><a href="#04-深入浅出索引-上" class="headerlink" title="04.深入浅出索引_上_"></a>04.深入浅出索引_上_</h1><h1 id="05-深入浅出索引-下"><a href="#05-深入浅出索引-下" class="headerlink" title="05.深入浅出索引_下_"></a>05.深入浅出索引_下_</h1><h1 id="06-全局锁和表锁-：给表加个字段怎么有这么多阻碍"><a href="#06-全局锁和表锁-：给表加个字段怎么有这么多阻碍" class="headerlink" title="06.全局锁和表锁 ：给表加个字段怎么有这么多阻碍?"></a>06.全局锁和表锁 ：给表加个字段怎么有这么多阻碍?</h1><h1 id="07-行锁功过：怎么减少行锁对性能的影响"><a href="#07-行锁功过：怎么减少行锁对性能的影响" class="headerlink" title="07.行锁功过：怎么减少行锁对性能的影响?"></a>07.行锁功过：怎么减少行锁对性能的影响?</h1><h1 id="08-事务到底是隔离的还是不隔离的"><a href="#08-事务到底是隔离的还是不隔离的" class="headerlink" title="08.事务到底是隔离的还是不隔离的?"></a>08.事务到底是隔离的还是不隔离的?</h1><h1 id="09-普通索引和唯一索引-应该怎么选择"><a href="#09-普通索引和唯一索引-应该怎么选择" class="headerlink" title="09.普通索引和唯一索引_应该怎么选择?"></a>09.普通索引和唯一索引_应该怎么选择?</h1><p>普通索引: </p><p>唯一索引: </p><p>普通索引在进行新增的时候不需要进行 重复的判断,而唯一索引需要</p><p>在查询的时候,唯一索引只需要查询到对应的值(从B+Tree的根节点一路下来)</p><p>如果是普通索引,在一个inooDB的一个页中,恰巧这条记录是本页的最后一条,则又需要进行一次IO来判断下一个inooDB页的第一个值等不等与要查询的值,但是对于inooDB来说,这种一页1000个索引的数据量,这个可能性会被CPU的速度认为忽略不计</p><h1 id="10-MySQL为什么有时候会选错索引"><a href="#10-MySQL为什么有时候会选错索引" class="headerlink" title="10.MySQL为什么有时候会选错索引?"></a>10.MySQL为什么有时候会选错索引?</h1><h1 id="11-怎么给字符串字段加索引"><a href="#11-怎么给字符串字段加索引" class="headerlink" title="11.怎么给字符串字段加索引?"></a>11.怎么给字符串字段加索引?</h1><h1 id="12-为什么我的MySQL会-抖-一下"><a href="#12-为什么我的MySQL会-抖-一下" class="headerlink" title="12.为什么我的MySQL会_抖_一下?"></a>12.为什么我的MySQL会_抖_一下?</h1><h1 id="13-为什么表数据删掉一半-表文件大小不变"><a href="#13-为什么表数据删掉一半-表文件大小不变" class="headerlink" title="13.为什么表数据删掉一半_表文件大小不变?"></a>13.为什么表数据删掉一半_表文件大小不变?</h1><h1 id="14-count-×-这么慢-我该怎么办"><a href="#14-count-×-这么慢-我该怎么办" class="headerlink" title="14.count(×)这么慢_我该怎么办?"></a>14.count(×)这么慢_我该怎么办?</h1><h1 id="15-答疑文章-一-：日志和索引相关问题"><a href="#15-答疑文章-一-：日志和索引相关问题" class="headerlink" title="15.答疑文章_一_：日志和索引相关问题"></a>15.答疑文章_一_：日志和索引相关问题</h1><h1 id="16-order-by-是怎么工作的"><a href="#16-order-by-是怎么工作的" class="headerlink" title="16._order by_是怎么工作的?"></a>16._order by_是怎么工作的?</h1><h1 id="17-如何正确地显示随机消息"><a href="#17-如何正确地显示随机消息" class="headerlink" title="17.如何正确地显示随机消息?"></a>17.如何正确地显示随机消息?</h1><h1 id="18-为什么这些SQL语句逻辑相同性能却差异巨大"><a href="#18-为什么这些SQL语句逻辑相同性能却差异巨大" class="headerlink" title="18.为什么这些SQL语句逻辑相同性能却差异巨大?"></a>18.为什么这些SQL语句逻辑相同性能却差异巨大?</h1><h1 id="18-为什么这些SQL语句逻辑相同-性能却差异巨大"><a href="#18-为什么这些SQL语句逻辑相同-性能却差异巨大" class="headerlink" title="18.为什么这些SQL语句逻辑相同_性能却差异巨大?"></a>18.为什么这些SQL语句逻辑相同_性能却差异巨大?</h1><h1 id="19-为什么我只查一行的语句也执行这么慢"><a href="#19-为什么我只查一行的语句也执行这么慢" class="headerlink" title="19.为什么我只查一行的语句也执行这么慢?"></a>19.为什么我只查一行的语句也执行这么慢?</h1><h1 id="19-为什么我只查一行的语句-也执行这么慢"><a href="#19-为什么我只查一行的语句-也执行这么慢" class="headerlink" title="19.为什么我只查一行的语句_也执行这么慢?"></a>19.为什么我只查一行的语句_也执行这么慢?</h1><h1 id="20-幻读是什么幻读有什么问题"><a href="#20-幻读是什么幻读有什么问题" class="headerlink" title="20.幻读是什么幻读有什么问题?"></a>20.幻读是什么幻读有什么问题?</h1><h1 id="21-为什么我只改一行的语句锁这么多"><a href="#21-为什么我只改一行的语句锁这么多" class="headerlink" title="21.为什么我只改一行的语句锁这么多?"></a>21.为什么我只改一行的语句锁这么多?</h1><h1 id="22-MySQL有哪些-饮鸩止渴-提高性能的方法"><a href="#22-MySQL有哪些-饮鸩止渴-提高性能的方法" class="headerlink" title="22.MySQL有哪些_饮鸩止渴_提高性能的方法?"></a>22.MySQL有哪些_饮鸩止渴_提高性能的方法?</h1><h1 id="23-MySQL是怎么保证数据不丢的"><a href="#23-MySQL是怎么保证数据不丢的" class="headerlink" title="23.MySQL是怎么保证数据不丢的?"></a>23.MySQL是怎么保证数据不丢的?</h1><h1 id="24-MySQL是怎么保证主备一致的"><a href="#24-MySQL是怎么保证主备一致的" class="headerlink" title="24.MySQL是怎么保证主备一致的?"></a>24.MySQL是怎么保证主备一致的?</h1><h1 id="25-MySQL是怎么保证高可用的"><a href="#25-MySQL是怎么保证高可用的" class="headerlink" title="25.MySQL是怎么保证高可用的?"></a>25.MySQL是怎么保证高可用的?</h1><h1 id="26-备库为什么会延迟好几个小时"><a href="#26-备库为什么会延迟好几个小时" class="headerlink" title="26.备库为什么会延迟好几个小时?"></a>26.备库为什么会延迟好几个小时?</h1><h1 id="27-主库出问题了从库怎么办"><a href="#27-主库出问题了从库怎么办" class="headerlink" title="27.主库出问题了从库怎么办?"></a>27.主库出问题了从库怎么办?</h1><h1 id="28-读写分离有哪些坑"><a href="#28-读写分离有哪些坑" class="headerlink" title="28.读写分离有哪些坑?"></a>28.读写分离有哪些坑?</h1><h1 id="29-如何判断一个数据库是不是出问题了"><a href="#29-如何判断一个数据库是不是出问题了" class="headerlink" title="29.如何判断一个数据库是不是出问题了?"></a>29.如何判断一个数据库是不是出问题了?</h1><h1 id="30-答疑文章-二-：用动态的观点看加锁"><a href="#30-答疑文章-二-：用动态的观点看加锁" class="headerlink" title="30.答疑文章_二_：用动态的观点看加锁"></a>30.答疑文章_二_：用动态的观点看加锁</h1><h1 id="31-误删数据后除了跑路还能怎么办"><a href="#31-误删数据后除了跑路还能怎么办" class="headerlink" title="31.误删数据后除了跑路还能怎么办?"></a>31.误删数据后除了跑路还能怎么办?</h1><h1 id="32-为什么还有kill不掉的语句"><a href="#32-为什么还有kill不掉的语句" class="headerlink" title="32.为什么还有kill不掉的语句?"></a>32.为什么还有kill不掉的语句?</h1><h1 id="33-我查这么多数据会不会把数据库内存打爆"><a href="#33-我查这么多数据会不会把数据库内存打爆" class="headerlink" title="33.我查这么多数据会不会把数据库内存打爆?"></a>33.我查这么多数据会不会把数据库内存打爆?</h1><h1 id="34-到底可不可以使用join"><a href="#34-到底可不可以使用join" class="headerlink" title="34.到底可不可以使用join?"></a>34.到底可不可以使用join?</h1><h1 id="35-join语句怎么优化"><a href="#35-join语句怎么优化" class="headerlink" title="35.join语句怎么优化?"></a>35.join语句怎么优化?</h1><h1 id="36-为什么临时表可以重名"><a href="#36-为什么临时表可以重名" class="headerlink" title="36.为什么临时表可以重名?"></a>36.为什么临时表可以重名?</h1><h1 id="37-什么时候会使用内部临时表"><a href="#37-什么时候会使用内部临时表" class="headerlink" title="37.什么时候会使用内部临时表?"></a>37.什么时候会使用内部临时表?</h1><h1 id="38-都说InnoDB好那还要不要使用Memory引擎"><a href="#38-都说InnoDB好那还要不要使用Memory引擎" class="headerlink" title="38.都说InnoDB好那还要不要使用Memory引擎?"></a>38.都说InnoDB好那还要不要使用Memory引擎?</h1><h1 id="39-自增主键为什么不是连续的"><a href="#39-自增主键为什么不是连续的" class="headerlink" title="39.自增主键为什么不是连续的?"></a>39.自增主键为什么不是连续的?</h1><h1 id="40-insert语句的锁为什么这么多"><a href="#40-insert语句的锁为什么这么多" class="headerlink" title="40.insert语句的锁为什么这么多?"></a>40.insert语句的锁为什么这么多?</h1><h1 id="41-怎么最快地复制一张表"><a href="#41-怎么最快地复制一张表" class="headerlink" title="41.怎么最快地复制一张表?"></a>41.怎么最快地复制一张表?</h1><h1 id="42-grant之后要跟着flush-privileges吗"><a href="#42-grant之后要跟着flush-privileges吗" class="headerlink" title="42.grant之后要跟着flush privileges吗?"></a>42.grant之后要跟着flush privileges吗?</h1><h1 id="43-要不要使用分区表"><a href="#43-要不要使用分区表" class="headerlink" title="43.要不要使用分区表?"></a>43.要不要使用分区表?</h1><h1 id="44-答疑文章-三-：说一说这些好问题"><a href="#44-答疑文章-三-：说一说这些好问题" class="headerlink" title="44.答疑文章_三_：说一说这些好问题"></a>44.答疑文章_三_：说一说这些好问题</h1><h1 id="45-自增id用完怎么办"><a href="#45-自增id用完怎么办" class="headerlink" title="45.自增id用完怎么办?"></a>45.自增id用完怎么办?</h1><h1 id=""><a href="#" class="headerlink" title=""></a></h1><p>查询的参数 只需要传 plan_number (表示第几种方案的航班计划)</p><p><strong>返回的数据如下</strong></p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;data&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;1&quot;</span>: &#123;</span><br><span class="line">      <span class="attr">&quot;66e804df98eb4fc58c8f55970fea3aa5&quot;</span>: &#123;</span><br><span class="line">        <span class="attr">&quot;plan&quot;</span>: &#123;</span><br><span class="line">          <span class="attr">&quot;plan_id&quot;</span>: <span class="string">&quot;66e804df98eb4fc58c8f55970fea3aa5&quot;</span>,</span><br><span class="line">          <span class="attr">&quot;plan_number&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">          <span class="attr">&quot;plan_name&quot;</span>: <span class="string">&quot;第一计划&quot;</span>,</span><br><span class="line">          <span class="attr">&quot;effect_status&quot;</span>: <span class="string">&quot;0&quot;</span>,</span><br><span class="line">          <span class="attr">&quot;begin_time&quot;</span>: <span class="string">&quot;2021-10-21T11:23:37Z&quot;</span>,</span><br><span class="line">          <span class="attr">&quot;end_time&quot;</span>: <span class="string">&quot;2021-11-22T11:23:37Z&quot;</span>,</span><br><span class="line">          <span class="attr">&quot;update_time&quot;</span>: <span class="string">&quot;2021-10-22T16:09:31.346704Z&quot;</span></span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="attr">&quot;task&quot;</span>: &#123;</span><br><span class="line">          <span class="attr">&quot;3&quot;</span>: [</span><br><span class="line">            &#123;</span><br><span class="line">              <span class="attr">&quot;task_id&quot;</span>: <span class="string">&quot;3505e9b90d75445cb5e5d4a820718c23&quot;</span>,</span><br><span class="line">              <span class="attr">&quot;plan_id&quot;</span>: <span class="string">&quot;66e804df98eb4fc58c8f55970fea3aa5&quot;</span>,</span><br><span class="line">              <span class="attr">&quot;week_number&quot;</span>: <span class="string">&quot;3&quot;</span>,</span><br><span class="line">              <span class="attr">&quot;executedate&quot;</span>: <span class="string">&quot;2021-09-14&quot;</span>,</span><br><span class="line">              <span class="attr">&quot;airway&quot;</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">              <span class="attr">&quot;flightno&quot;</span>: <span class="string">&quot;KN5519&quot;</span>,</span><br></pre></td></tr></table></figure><ul><li>第一级的数字(key)”1”表示 10个计划中的第一个</li><li>第二级的数字(key)”66e804df98eb4fc58c8f55970fea3aa5”</li><li>“66e804df98eb4fc58c8f55970fea3aa5”下的plan里是计划信息</li><li>task下的(key) “3” 表示 每周的星期数(星期一:1,星期二:2,,星期三:3…)</li><li> “3”下面是航班模板的数组,里面的结构和航班信息是一样的(多了task_id,plan_id,week_number)</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MySQL的索引与优化</title>
      <link href="database/mysql/index-optimize/"/>
      <url>database/mysql/index-optimize/</url>
      
        <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面:"></a>写在前面:</h2><h3 id="TO-KNOW"><a href="#TO-KNOW" class="headerlink" title="TO KNOW"></a>TO KNOW</h3><ul><li>MySQL索引定义</li><li>MySQL索引结构</li><li>MySQL索引优势</li></ul><p>写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录.如果没有索引,查询将对整个表进行扫描,最坏的情况下,如果所有数据页,需要读取10^4个页面,如果这10^4个页面在磁盘上下随机分布,需要需要进行10^4次I/O,假设磁盘每次I/O时间为10ms(忽略数据传输时间),则总共需要100s(但实际上要好很多很多).如果对之建立B-Tree索引,则只需要进行log100(10^6)=3次页面读取,最坏情况下耗时30ms.这就是索引带来的效果,很多时候,当你的应用程序进行SQL查询速度很慢时,应该想想是否可以建索引.进入正题:</p><h2 id="索引与优化"><a href="#索引与优化" class="headerlink" title="索引与优化"></a>索引与优化</h2><h3 id="1-选择索引的数据类型"><a href="#1-选择索引的数据类型" class="headerlink" title="1. 选择索引的数据类型"></a>1. 选择索引的数据类型</h3><p>MySQL支持很多数据类型,选择合适的数据类型存储数据对性能有很大影响.</p><p>通常来说,可以遵循以下一些指导原则:</p><ul><li><strong>越小的数据类型通常更好</strong>:越小的数据类型通常在磁盘,内存和CPU缓存中都需要更少的空间,处理起来更快.</li><li><strong>简单的数据类型更好</strong>:整形数据比起字符,处理开销更小,因为字符串的比较更复杂. 在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储时间;以及用整型数据类型存储IP地址.</li><li>**尽量避免NULL:**应该指定列为NOT NULL,除非你想存储NULL.在MySQL中,含有空值的列很难进行查询优化,因为他们使得索引,索引的统计信息以及比较运算更加复杂.你应该用0,一个特除的值或者一个空串代替空值.</li></ul><h4 id="选择标识符"><a href="#选择标识符" class="headerlink" title="选择标识符"></a>选择标识符</h4><p>选择合适的标识符是非常重要的.选择时不仅应该考虑存储类型,而且应该考虑MySQL是怎样进行运算和比较的.一旦选定数据类型,应该保证所有相关的表都使用相同的数据类型.</p><ul><li>整型: 通常是作为标识符的最好选择,因为可以更快的处理,而且可以设置为AUTO_INCREMENT.</li><li>字符串: 尽量避免使用字符串作为标识符,它们消耗更好的空间,处理起来也较慢.而且,通常来说,字符串都是随机的,所以他们在索引中的位置也是随机的,这会导致页面分裂,随机访问磁盘,聚簇索引分裂(对于使用聚簇索引的存储引擎).</li></ul><h3 id="2-索引的入口"><a href="#2-索引的入口" class="headerlink" title="2. 索引的入口"></a>2. 索引的入口</h3><p>对于任何<a href="https://blog.csdn.net/gengkui9897/article/details/89294936">DBMS</a>,索引都是进行优化的最主要的因素.对于少量的数据,没有合适的索引影响不是很大,但是,当随着数据量的增加,性能会急剧下降.</p><p>如果对多列进行索引(组合索引),列的顺序非常重要,MySQL仅能对索引最左边的前缀进行有效的查找.例如:</p><p>假设存在组合索引it1c1c2(c1,c2)，查询语句select * from t1 where c1=1 and c2=2能够使用该索引。查询语句select * from t1 where c1=1也能够使用该索引。但是，查询语句select * from t1 where c2=2不能够使用该索引，因为没有组合索引的引导列，即，要想使用c2列进行查找，必需出现c1等于某值。</p><h4 id="索引的类型"><a href="#索引的类型" class="headerlink" title="索引的类型"></a>索引的类型</h4><p>索引是在存储引擎中实现的,而不是在服务器层中实现的.所以,每种存储引擎的索引类型都不一定完全相同,并不是所有的存储引擎都支持所有的索引类型.</p><h5 id="B-Tree-索引"><a href="#B-Tree-索引" class="headerlink" title="B-Tree 索引"></a>B-Tree 索引</h5><p><a href="https://victorfengming.gitee.io/data_algorithm/135_%E6%A0%91_%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91_AVL%E6%A0%91_%E4%BB%8B%E7%BB%8D.html">B-Tree(balance Tree)</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java遍历对象所有属性</title>
      <link href="cp/java/for-props/"/>
      <url>cp/java/for-props/</url>
      
        <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><blockquote><p>要获取对象的所有属性可以使用<code>getDeclaredFields()</code></p><p>方法会返回一个<code>Field</code>数组</p></blockquote><p>遍历这个数组几个遍历所有属性</p><blockquote><p>注意: 使用这个方法会抛出4个异常</p><p>然后,根据属性的类型选择执行对应的内容</p></blockquote><h2 id="代码演示"><a href="#代码演示" class="headerlink" title="代码演示"></a>代码演示</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">eachProperties</span><span class="params">(Object model)</span> <span class="keyword">throws</span> NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException</span>&#123;</span><br><span class="line">    Field[] field = model.getClass().getDeclaredFields(); <span class="comment">//获取实体类的所有属性，返回Field数组</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span> ; j&lt;field.length ; j++)&#123; <span class="comment">//遍历所有属性</span></span><br><span class="line">        String name = field[j].getName(); <span class="comment">//获取属性的名字</span></span><br><span class="line"> </span><br><span class="line">        System.out.println(<span class="string">&quot;attribute name:&quot;</span>+name);</span><br><span class="line">        name = name.substring(<span class="number">0</span>,<span class="number">1</span>).toUpperCase()+name.substring(<span class="number">1</span>); <span class="comment">//将属性的首字符大写，方便构造get，set方法</span></span><br><span class="line">        String type = field[j].getGenericType().toString(); <span class="comment">//获取属性的类型</span></span><br><span class="line">        <span class="keyword">if</span>(type.equals(<span class="string">&quot;class java.lang.String&quot;</span>))&#123; <span class="comment">//如果type是类类型，则前面包含&quot;class &quot;，后面跟类名</span></span><br><span class="line">          ...</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(type.equals(<span class="string">&quot;class java.lang.Integer&quot;</span>))&#123;</span><br><span class="line">          ...</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(type.equals(<span class="string">&quot;class java.lang.Short&quot;</span>))&#123;</span><br><span class="line">          ...</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(type.equals(<span class="string">&quot;class java.lang.Double&quot;</span>))&#123;</span><br><span class="line">          ...</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(type.equals(<span class="string">&quot;class java.lang.Boolean&quot;</span>))&#123;</span><br><span class="line">          ...</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(type.equals(<span class="string">&quot;class java.util.Date&quot;</span>))&#123;</span><br><span class="line">          ...</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>具体执行的内容就是重点了</p></blockquote><p>我们知道模型的属性都会有对应的<code>getter</code>和<code>setter</code>方法</p><p>只需要得到对应的<code>getter</code>和<code>setter</code>方法即可获取和设置属性</p><blockquote><p>这里就需要用到getMethod方法</p></blockquote><h2 id="获得getter方法"><a href="#获得getter方法" class="headerlink" title="获得getter方法"></a>获得getter方法</h2><blockquote><p>方法有分带参数和不带参数,我们知道getter方法是不带参数的</p></blockquote><p>获得getter方法如下</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Method m = model.getClass().getMethod(<span class="string">&quot;get&quot;</span>+name);</span><br></pre></td></tr></table></figure><h2 id="获得setter方法"><a href="#获得setter方法" class="headerlink" title="获得setter方法"></a>获得setter方法</h2><blockquote><p>如果是带参数的setter方法,就应该把参数的类型做封装成一个Class&lt;?&gt;泛型数组传入getMethod方法的第二个参数</p></blockquote><p>例如参数是String类型的setter方法如下</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Method m = model.getClass().getMethod(<span class="string">&quot;set&quot;</span>+name, <span class="keyword">new</span> Class[] &#123;String.class&#125;);</span><br></pre></td></tr></table></figure><h2 id="执行getter方法"><a href="#执行getter方法" class="headerlink" title="执行getter方法"></a>执行getter方法</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String value = (String) m.invoke(model);</span><br></pre></td></tr></table></figure><h2 id="执行setter方法"><a href="#执行setter方法" class="headerlink" title="执行setter方法"></a>执行setter方法</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">m.invoke(model,<span class="keyword">new</span> Object[] &#123;<span class="keyword">new</span> String(<span class="string">&quot;new value&quot;</span>)&#125;);</span><br></pre></td></tr></table></figure><h2 id="链接"><a href="#链接" class="headerlink" title="链接"></a>链接</h2><p>参考: from: <a href="http://zhenhappy.github.io/2015/10/26/Java/Java-Each-Properties/">http://zhenhappy.github.io/2015/10/26/Java/Java-Each-Properties/</a></p><p>转载于:<a href="https://www.cnblogs.com/GarfieldEr007/p/7056817.html">https://www.cnblogs.com/GarfieldEr007/p/7056817.html</a></p><p>原文: <a href="https://blog.csdn.net/weixin_30588675/article/details/97631029">https://blog.csdn.net/weixin_30588675/article/details/97631029</a></p><h2 id="java-获取类和父类的属性和方法"><a href="#java-获取类和父类的属性和方法" class="headerlink" title="java 获取类和父类的属性和方法"></a>java 获取类和父类的属性和方法</h2><h3 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h3><p>在日常开发中，经常需要获取当前类和父类的所有属性，没办法只能查API了。</p><h3 id="getDeclaredFields-VS-getFields"><a href="#getDeclaredFields-VS-getFields" class="headerlink" title="getDeclaredFields VS getFields"></a>getDeclaredFields VS getFields</h3><p>查阅API得知，class.getDeclaredFields()能获取所有属性（public、protected、default、private），但不包括父类属性，相对的class.getFields() 获取类的属性（public），包括父类；</p><p>显然以上二者都不能满足需求，这么常见的需求，肯定有开源包实现了，功夫不负有心人果然查到了。apache commons包下的FieldUtils.getAllFields()可以获取类和父类的所有(public、protected、default、private)属性。</p><p>为了加深理解，看一下源码</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Field[] getAllFields(<span class="keyword">final</span> Class&lt;?&gt; cls) &#123;</span><br><span class="line">       <span class="keyword">final</span> List&lt;Field&gt; allFieldsList = getAllFieldsList(cls);</span><br><span class="line">       <span class="keyword">return</span> allFieldsList.toArray(<span class="keyword">new</span> Field[allFieldsList.size()]);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> List&lt;Field&gt; <span class="title">getAllFieldsList</span><span class="params">(<span class="keyword">final</span> Class&lt;?&gt; cls)</span> </span>&#123;</span><br><span class="line">       Validate.isTrue(cls != <span class="keyword">null</span>, <span class="string">&quot;The class must not be null&quot;</span>);</span><br><span class="line">       <span class="keyword">final</span> List&lt;Field&gt; allFields = <span class="keyword">new</span> ArrayList&lt;Field&gt;();</span><br><span class="line">       Class&lt;?&gt; currentClass = cls;</span><br><span class="line">       <span class="keyword">while</span> (currentClass != <span class="keyword">null</span>) &#123;</span><br><span class="line">           <span class="keyword">final</span> Field[] declaredFields = currentClass.getDeclaredFields();</span><br><span class="line">           <span class="keyword">for</span> (<span class="keyword">final</span> Field field : declaredFields) &#123;</span><br><span class="line">               allFields.add(field);</span><br><span class="line">           &#125;</span><br><span class="line">           currentClass = currentClass.getSuperclass();</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> allFields;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure><p>通过class.getDeclaredFields()获取所有的属性，然后再获取类的父类，再获取所有属性，直到父类为null截止；</p><h3 id="获取类和父类的方法"><a href="#获取类和父类的方法" class="headerlink" title="获取类和父类的方法"></a>获取类和父类的方法</h3><p>类似的，API中也有getDeclaredMethods()和getMethods()</p><p>class.getDeclaredMethods() 获取类的所有方法（public、protected、default、private），但不包括继承的方法；</p><p>class.getMethods() 获取当前类和父类的public方法。</p><p>apache commons包提供了MethodUtils.getMethodsWithAnnotation(class,annotation),获取类及父类的注解为annotation的public方法；</p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul><li>获取类的所有属性（public、protected、default、private），包括父类的属性，则使用FieldUtils.getAllFields()</li><li>获取类标注某个注解的方法（包括类及父类），使用MethodUtils.getMethodsWithAnnotation(class,annotation)</li></ul><p>原文: <a href="https://blog.csdn.net/wangjun5159/article/details/79289244/">https://blog.csdn.net/wangjun5159/article/details/79289244/</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jFinal配置自动生成</title>
      <link href="java/jfinal/collected/"/>
      <url>java/jfinal/collected/</url>
      
        <content type="html"><![CDATA[<h3 id="Jfinal配置自动生成model"><a href="#Jfinal配置自动生成model" class="headerlink" title="Jfinal配置自动生成model"></a>Jfinal配置自动生成model</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.demo.common.model;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.sql.DataSource;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.jfinal.kit.PathKit;</span><br><span class="line"><span class="keyword">import</span> com.jfinal.plugin.activerecord.dialect.PostgreSqlDialect;</span><br><span class="line"><span class="keyword">import</span> com.jfinal.plugin.activerecord.generator.Generator;</span><br><span class="line"><span class="keyword">import</span> com.jfinal.plugin.druid.DruidPlugin;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 本 demo 仅表达最为粗浅的 jfinal 用法，更为有价值的实用的企业级用法 详见 JFinal 俱乐部:</span></span><br><span class="line"><span class="comment"> * http://jfinal.com/club</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * 在数据库表有任何变动时，运行一下 main 方法，极速响应变化进行代码重构</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">_JFinalDemoGenerator</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> DataSource <span class="title">getDataSource</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        DruidPlugin druidPlugin = <span class="keyword">new</span> DruidPlugin(</span><br><span class="line">                <span class="string">&quot;jdbc:postgresql://localhost:5444/console1?currentSchema=console1&quot;</span>, <span class="string">&quot;username&quot;</span>, <span class="string">&quot;password&quot;</span>);</span><br><span class="line">        druidPlugin.start();</span><br><span class="line">        <span class="keyword">return</span> druidPlugin.getDataSource();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// base model 所使用的包名</span></span><br><span class="line">        String baseModelPackageName = <span class="string">&quot;com.model.base&quot;</span>;</span><br><span class="line">        <span class="comment">// base model 文件保存路径</span></span><br><span class="line">        String baseModelOutputDir = PathKit.getWebRootPath()</span><br><span class="line">                + <span class="string">&quot;/src/main/java/com/model/base&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// model 所使用的包名 (MappingKit 默认使用的包名)</span></span><br><span class="line">        String modelPackageName = <span class="string">&quot;com.model&quot;</span>;</span><br><span class="line">        <span class="comment">// model 文件保存路径 (MappingKit 与 DataDictionary 文件默认保存路径)</span></span><br><span class="line">        String modelOutputDir = baseModelOutputDir + <span class="string">&quot;/..&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 创建生成器</span></span><br><span class="line">        Generator generator = <span class="keyword">new</span> Generator(getDataSource(), baseModelPackageName, baseModelOutputDir, modelPackageName,</span><br><span class="line">                modelOutputDir);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 配置是否生成备注</span></span><br><span class="line">        generator.setGenerateRemarks(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 设置数据库方言</span></span><br><span class="line">        generator.setDialect(<span class="keyword">new</span> PostgreSqlDialect());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 设置是否生成链式 setter 方法</span></span><br><span class="line">        generator.setGenerateChainSetter(<span class="keyword">false</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 添加不需要生成的表名</span></span><br><span class="line">        generator.addExcludedTable(<span class="string">&quot;adv&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 设置是否在 Model 中生成 dao 对象</span></span><br><span class="line">        generator.setGenerateDaoInModel(<span class="keyword">false</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 设置是否生成字典文件</span></span><br><span class="line">        generator.setGenerateDataDictionary(<span class="keyword">false</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 设置需要被移除的表名前缀用于生成modelName。例如表名 &quot;osc_user&quot;，移除前缀 &quot;osc_&quot;后生成的model名为</span></span><br><span class="line">        <span class="comment">// &quot;User&quot;而非 OscUser</span></span><br><span class="line">        generator.setMetaBuilder(<span class="keyword">new</span> SelfMetaBuilder(getDataSource()));</span><br><span class="line"></span><br><span class="line">        generator.setGenerateChainSetter(<span class="keyword">true</span>);</span><br><span class="line">        <span class="comment">// 生成</span></span><br><span class="line">        generator.generate();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">package</span> com.demo.common.model;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.ResultSet;</span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.sql.DataSource;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.jfinal.plugin.activerecord.generator.MetaBuilder;</span><br><span class="line"><span class="keyword">import</span> com.jfinal.plugin.activerecord.generator.TableMeta;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SelfMetaBuilder</span> <span class="keyword">extends</span> <span class="title">MetaBuilder</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Creates a new instance of SelfMetaBuilder.&lt;br/&gt;</span></span><br><span class="line"><span class="comment">     * Description: TODO&lt;br/&gt;</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> dataSource</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">SelfMetaBuilder</span><span class="params">(DataSource dataSource)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(dataSource);</span><br><span class="line">        <span class="comment">// TODO Auto-generated constructor stub</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">buildTableNames</span><span class="params">(List&lt;TableMeta&gt; ret)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        ResultSet rs = getTablesResultSet();</span><br><span class="line">        <span class="keyword">while</span> (rs.next()) &#123;</span><br><span class="line">            String tableName = rs.getString(<span class="string">&quot;TABLE_NAME&quot;</span>);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (!tableName.startsWith(<span class="string">&quot;blog_&quot;</span>)) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Skip table :&quot;</span> + tableName);</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (isSkipTable(tableName)) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Skip table :&quot;</span> + tableName);</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// jfinal 4.3 新增过滤 table 机制</span></span><br><span class="line">            <span class="keyword">if</span> (filterPredicate != <span class="keyword">null</span> &amp;&amp; filterPredicate.test(tableName)) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Skip table :&quot;</span> + tableName);</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            TableMeta tableMeta = <span class="keyword">new</span> TableMeta();</span><br><span class="line">            tableMeta.name = tableName;</span><br><span class="line">            tableMeta.remarks = rs.getString(<span class="string">&quot;REMARKS&quot;</span>);</span><br><span class="line"></span><br><span class="line">            tableMeta.modelName = buildModelName(tableName);</span><br><span class="line">            tableMeta.baseModelName = buildBaseModelName(tableMeta.modelName);</span><br><span class="line">            ret.add(tableMeta);</span><br><span class="line">        &#125;</span><br><span class="line">        rs.close();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Jfinal-初始化"><a href="#Jfinal-初始化" class="headerlink" title="Jfinal 初始化"></a>Jfinal 初始化</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DemoConfig</span> <span class="keyword">extends</span> <span class="title">JFinalConfig</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">configPlugin</span><span class="params">(Plugins me)</span> </span>&#123;</span><br><span class="line">  DruidPlugin dp = <span class="keyword">new</span> DruidPlugin(<span class="string">&quot;jdbc:mysql://localhost/db_name&quot;</span>, <span class="string">&quot;userName&quot;</span>, <span class="string">&quot;password&quot;</span>);</span><br><span class="line">    me.add(dp);</span><br><span class="line">    ActiveRecordPlugin arp = <span class="keyword">new</span> ActiveRecordPlugin(dp);</span><br><span class="line">    me.add(arp);</span><br><span class="line">    arp.addMapping(<span class="string">&quot;user&quot;</span>, User.class);</span><br><span class="line">    arp.addMapping(<span class="string">&quot;article&quot;</span>, <span class="string">&quot;article_id&quot;</span>, Article.class);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>更多: <a href="https://jfinal.com/doc/5-2">官方文档5.2 ActiveRecordPlugin</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
            <tag> jFinal </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Redis哨兵（Sentinel）模式</title>
      <link href="database/redis/redis-Sentinel/"/>
      <url>database/redis/redis-Sentinel/</url>
      
        <content type="html"><![CDATA[<p>主从切换技术的方法是：当主服务器宕机后，需要手动把一台从服务器切换为主服务器，这就需要人工干预，费事费力，还会造成一段时间内服务不可用。这不是一种推荐的方式，更多时候，我们优先考虑哨兵模式。</p><h2 id="一、哨兵模式概述"><a href="#一、哨兵模式概述" class="headerlink" title="一、哨兵模式概述"></a>一、哨兵模式概述</h2><p>哨兵模式是一种特殊的模式，首先Redis提供了哨兵的命令，哨兵是一个独立的进程，作为进程，它会独立运行。其原理是哨兵通过发送命令，等待Redis服务器响应，从而监控运行的多个Redis实例。</p><p> <img src= "/img/loading.gif" data-lazy-src="11320039-57a77ca2757d0924.webp" alt="img"> </p><p>这里的哨兵有两个作用</p><ul><li>通过发送命令，让Redis服务器返回监控其运行状态，包括主服务器和从服务器。</li><li>当哨兵监测到master宕机，会自动将slave切换成master，然后通过<strong>发布订阅模式</strong>通知其他的从服务器，修改配置文件，让它们切换主机。</li></ul><p>然而一个哨兵进程对Redis服务器进行监控，可能会出现问题，为此，我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控，这样就形成了多哨兵模式。</p><p>用文字描述一下<strong>故障切换（failover）</strong>的过程。假设主服务器宕机，哨兵1先检测到这个结果，系统并不会马上进行failover过程，仅仅是哨兵1主观的认为主服务器不可用，这个现象成为<strong>主观下线</strong>。当后面的哨兵也检测到主服务器不可用，并且数量达到一定值时，那么哨兵之间就会进行一次投票，投票的结果由一个哨兵发起，进行failover操作。切换成功后，就会通过发布订阅模式，让各个哨兵把自己监控的从服务器实现切换主机，这个过程称为<strong>客观下线</strong>。这样对于客户端而言，一切都是透明的。</p><h2 id="二、Redis配置哨兵模式"><a href="#二、Redis配置哨兵模式" class="headerlink" title="二、Redis配置哨兵模式"></a>二、Redis配置哨兵模式</h2><p>配置3个哨兵和1主2从的Redis服务器来演示这个过程。</p><table><thead><tr><th>服务类型</th><th>是否是主服务器</th><th>IP地址</th><th>端口</th></tr></thead><tbody><tr><td>Redis</td><td>是</td><td>192.168.11.128</td><td>6379</td></tr><tr><td>Redis</td><td>否</td><td>192.168.11.129</td><td>6379</td></tr><tr><td>Redis</td><td>否</td><td>192.168.11.130</td><td>6379</td></tr><tr><td>Sentinel</td><td>-</td><td>192.168.11.128</td><td>26379</td></tr><tr><td>Sentinel</td><td>-</td><td>192.168.11.129</td><td>26379</td></tr><tr><td>Sentinel</td><td>-</td><td>192.168.11.130</td><td>26379</td></tr></tbody></table><p> <img src= "/img/loading.gif" data-lazy-src="11320039-3f40b17c0412116c.webp" alt="img"> </p><p>首先配置Redis的主从服务器，修改redis.conf文件如下</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使得Redis服务器可以跨网络访问</span></span><br><span class="line"><span class="built_in">bind</span> 0.0.0.0</span><br><span class="line"><span class="comment"># 设置密码</span></span><br><span class="line">requirepass <span class="string">&quot;123456&quot;</span></span><br><span class="line"><span class="comment"># 指定主服务器，注意：有关slaveof的配置只是配置从服务器，主服务器不需要配置</span></span><br><span class="line">slaveof 192.168.11.128 6379</span><br><span class="line"><span class="comment"># 主服务器密码，注意：有关slaveof的配置只是配置从服务器，主服务器不需要配置</span></span><br><span class="line">masterauth 123456</span><br></pre></td></tr></table></figure><p>上述内容主要是配置Redis服务器，从服务器比主服务器多一个slaveof的配置和密码。</p><p>配置3个哨兵，每个哨兵的配置都是一样的。在Redis安装目录下有一个sentinel.conf文件，copy一份进行修改</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># 禁止保护模式</span><br><span class="line">protected-mode no</span><br><span class="line"># 配置监听的主服务器，这里sentinel monitor代表监控，mymaster代表服务器的名称，可以自定义，<span class="number">192.168</span>.<span class="number">11.128</span>代表监控的主服务器，<span class="number">6379</span>代表端口，<span class="number">2</span>代表只有两个或两个以上的哨兵认为主服务器不可用的时候，才会进行failover操作。</span><br><span class="line">sentinel monitor mymaster <span class="number">192.168</span>.<span class="number">11.128</span> <span class="number">6379</span> <span class="number">2</span></span><br><span class="line"># sentinel author-pass定义服务的密码，mymaster是服务名称，<span class="number">123456</span>是Redis服务器密码</span><br><span class="line"># sentinel auth-pass &lt;master-name&gt; &lt;password&gt;</span><br><span class="line">sentinel auth-pass mymaster <span class="number">123456</span></span><br></pre></td></tr></table></figure><p>上述关闭了保护模式，便于测试。</p><p>有了上述的修改，我们可以进入Redis的安装目录的src目录，通过下面的命令启动服务器和哨兵</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启动Redis服务器进程</span></span><br><span class="line">./redis-server ../redis.conf</span><br><span class="line"><span class="comment"># 启动哨兵进程</span></span><br><span class="line">./redis-sentinel ../sentinel.conf</span><br></pre></td></tr></table></figure><p> 注意启动的顺序。<strong>首先是主机（192.168.11.128）的Redis服务进程，然后启动从机的服务进程，最后启动3个哨兵的服务进程。</strong> </p><h2 id="三、Java中使用哨兵模式"><a href="#三、Java中使用哨兵模式" class="headerlink" title="三、Java中使用哨兵模式"></a>三、Java中使用哨兵模式</h2><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 测试Redis哨兵模式</span></span><br><span class="line"><span class="comment"> * @author liu</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">TestSentinels</span> &#123;</span><br><span class="line">    @SuppressWarnings(<span class="string">&quot;resource&quot;</span>)</span><br><span class="line">    @Test</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSentinel</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        JedisPoolConfig jedisPoolConfig = <span class="keyword">new</span> JedisPoolConfig();</span><br><span class="line">        jedisPoolConfig.setMaxTotal(<span class="number">10</span>);</span><br><span class="line">        jedisPoolConfig.setMaxIdle(<span class="number">5</span>);</span><br><span class="line">        jedisPoolConfig.setMinIdle(<span class="number">5</span>);</span><br><span class="line">        <span class="comment">// 哨兵信息</span></span><br><span class="line">        Set&lt;String&gt; sentinels = <span class="keyword">new</span> HashSet&lt;&gt;(Arrays.asList(<span class="string">&quot;192.168.11.128:26379&quot;</span>,</span><br><span class="line">                <span class="string">&quot;192.168.11.129:26379&quot;</span>,<span class="string">&quot;192.168.11.130:26379&quot;</span>));</span><br><span class="line">        <span class="comment">// 创建连接池</span></span><br><span class="line">        JedisSentinelPool pool = <span class="keyword">new</span> JedisSentinelPool(<span class="string">&quot;mymaster&quot;</span>, sentinels,jedisPoolConfig,<span class="string">&quot;123456&quot;</span>);</span><br><span class="line">        <span class="comment">// 获取客户端</span></span><br><span class="line">        Jedis jedis = pool.getResource();</span><br><span class="line">        <span class="comment">// 执行两个命令</span></span><br><span class="line">        jedis.<span class="keyword">set</span>(<span class="string">&quot;mykey&quot;</span>, <span class="string">&quot;myvalue&quot;</span>);</span><br><span class="line">        String <span class="keyword">value</span> = jedis.<span class="keyword">get</span>(<span class="string">&quot;mykey&quot;</span>);</span><br><span class="line">        System.<span class="keyword">out</span>.println(<span class="keyword">value</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p> 上面是通过Jedis进行使用的，同样也可以使用Spring进行配置RedisTemplate使用。 </p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line">&lt;bean id = <span class="string">&quot;poolConfig&quot;</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">&quot;redis.clients.jedis.JedisPoolConfig&quot;</span>&gt;</span><br><span class="line">    &lt;!-- 最大空闲数 --&gt;</span><br><span class="line">    &lt;property name=<span class="string">&quot;maxIdle&quot;</span> value=<span class="string">&quot;50&quot;</span>&gt;&lt;/property&gt;</span><br><span class="line">    &lt;!-- 最大连接数 --&gt;</span><br><span class="line">    &lt;property name=<span class="string">&quot;maxTotal&quot;</span> value=<span class="string">&quot;100&quot;</span>&gt;&lt;/property&gt;</span><br><span class="line">    &lt;!-- 最大等待时间 --&gt;</span><br><span class="line">    &lt;property name=<span class="string">&quot;maxWaitMillis&quot;</span> value=<span class="string">&quot;20000&quot;</span>&gt;&lt;/property&gt;</span><br><span class="line">&lt;/bean&gt;</span><br><span class="line"></span><br><span class="line">&lt;bean id=<span class="string">&quot;connectionFactory&quot;</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">&quot;org.springframework.data.redis.connection.jedis.JedisConnectionFactory&quot;</span>&gt;</span><br><span class="line">    &lt;<span class="title">constructor</span>-<span class="title">arg</span> <span class="title">name</span>=&quot;<span class="title">poolConfig</span>&quot; <span class="title">ref</span>=&quot;<span class="title">poolConfig</span>&quot;&gt;&lt;/<span class="title">constructor</span>-<span class="title">arg</span>&gt;</span><br><span class="line">    &lt;<span class="title">constructor</span>-<span class="title">arg</span> <span class="title">name</span>=&quot;<span class="title">sentinelConfig</span>&quot; <span class="title">ref</span>=&quot;<span class="title">sentinelConfig</span>&quot;&gt;&lt;/<span class="title">constructor</span>-<span class="title">arg</span>&gt;</span><br><span class="line">    &lt;<span class="title">property</span> <span class="title">name</span>=&quot;<span class="title">password</span>&quot; <span class="title">value</span>=&quot;123456&quot;&gt;&lt;/<span class="title">property</span>&gt;</span><br><span class="line">&lt;/<span class="title">bean</span>&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- <span class="title">JDK</span>序列化器 --&gt;</span><br><span class="line">&lt;<span class="title">bean</span> <span class="title">id</span>=&quot;<span class="title">jdkSerializationRedisSerializer</span>&quot; <span class="title">class</span>=&quot;<span class="title">org</span>.<span class="title">springframework</span>.<span class="title">data</span>.<span class="title">redis</span>.<span class="title">serializer</span>.<span class="title">JdkSerializationRedisSerializer</span>&quot;&gt;&lt;/<span class="title">bean</span>&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- <span class="title">String</span>序列化器 --&gt;</span><br><span class="line">&lt;<span class="title">bean</span> <span class="title">id</span>=&quot;<span class="title">stringRedisSerializer</span>&quot; <span class="title">class</span>=&quot;<span class="title">org</span>.<span class="title">springframework</span>.<span class="title">data</span>.<span class="title">redis</span>.<span class="title">serializer</span>.<span class="title">StringRedisSerializer</span>&quot;&gt;&lt;/<span class="title">bean</span>&gt;</span><br><span class="line"></span><br><span class="line">&lt;<span class="title">bean</span> <span class="title">id</span>=&quot;<span class="title">redisTemplate</span>&quot; <span class="title">class</span>=&quot;<span class="title">org</span>.<span class="title">springframework</span>.<span class="title">data</span>.<span class="title">redis</span>.<span class="title">core</span>.<span class="title">RedisTemplate</span>&quot;&gt;</span><br><span class="line">    &lt;<span class="title">property</span> <span class="title">name</span>=&quot;<span class="title">connectionFactory</span>&quot; <span class="title">ref</span>=&quot;<span class="title">connectionFactory</span>&quot;&gt;&lt;/<span class="title">property</span>&gt;</span><br><span class="line">    &lt;<span class="title">property</span> <span class="title">name</span>=&quot;<span class="title">keySerializer</span>&quot; <span class="title">ref</span>=&quot;<span class="title">stringRedisSerializer</span>&quot;&gt;&lt;/<span class="title">property</span>&gt;</span><br><span class="line">    &lt;<span class="title">property</span> <span class="title">name</span>=&quot;<span class="title">defaultSerializer</span>&quot; <span class="title">ref</span>=&quot;<span class="title">stringRedisSerializer</span>&quot;&gt;&lt;/<span class="title">property</span>&gt;</span><br><span class="line">    &lt;<span class="title">property</span> <span class="title">name</span>=&quot;<span class="title">valueSerializer</span>&quot; <span class="title">ref</span>=&quot;<span class="title">jdkSerializationRedisSerializer</span>&quot;&gt;&lt;/<span class="title">property</span>&gt;</span><br><span class="line">&lt;/<span class="title">bean</span>&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- 哨兵配置 --&gt;</span><br><span class="line">&lt;<span class="title">bean</span> <span class="title">id</span>=&quot;<span class="title">sentinelConfig</span>&quot; <span class="title">class</span>=&quot;<span class="title">org</span>.<span class="title">springframework</span>.<span class="title">data</span>.<span class="title">redis</span>.<span class="title">connection</span>.<span class="title">RedisSentinelConfiguration</span>&quot;&gt;</span><br><span class="line">    &lt;!-- 服务名称 --&gt;</span><br><span class="line">    &lt;<span class="title">property</span> <span class="title">name</span>=&quot;<span class="title">master</span>&quot;&gt;</span><br><span class="line">        &lt;<span class="title">bean</span> <span class="title">class</span>=&quot;<span class="title">org</span>.<span class="title">springframework</span>.<span class="title">data</span>.<span class="title">redis</span>.<span class="title">connection</span>.<span class="title">RedisNode</span>&quot;&gt;</span><br><span class="line">            &lt;<span class="title">property</span> <span class="title">name</span>=&quot;<span class="title">name</span>&quot; <span class="title">value</span>=&quot;<span class="title">mymaster</span>&quot;&gt;&lt;/<span class="title">property</span>&gt;</span><br><span class="line">        &lt;/<span class="title">bean</span>&gt;</span><br><span class="line">    &lt;/<span class="title">property</span>&gt;</span><br><span class="line">    &lt;!-- 哨兵服务<span class="title">IP</span>和端口 --&gt;</span><br><span class="line">    &lt;<span class="title">property</span> <span class="title">name</span>=&quot;<span class="title">sentinels</span>&quot;&gt;</span><br><span class="line">        &lt;<span class="title">set</span>&gt;</span><br><span class="line">            &lt;<span class="title">bean</span> <span class="title">class</span>=&quot;<span class="title">org</span>.<span class="title">springframework</span>.<span class="title">data</span>.<span class="title">redis</span>.<span class="title">connection</span>.<span class="title">RedisNode</span>&quot;&gt;</span><br><span class="line">                &lt;<span class="title">constructor</span>-<span class="title">arg</span> <span class="title">name</span>=&quot;<span class="title">host</span>&quot; <span class="title">value</span>=&quot;192.168.11.128&quot;&gt;&lt;/<span class="title">constructor</span>-<span class="title">arg</span>&gt;</span><br><span class="line">                &lt;<span class="title">constructor</span>-<span class="title">arg</span> <span class="title">name</span>=&quot;<span class="title">port</span>&quot; <span class="title">value</span>=&quot;26379&quot;&gt;&lt;/<span class="title">constructor</span>-<span class="title">arg</span>&gt;</span><br><span class="line">            &lt;/<span class="title">bean</span>&gt;</span><br><span class="line">            &lt;<span class="title">bean</span> <span class="title">class</span>=&quot;<span class="title">org</span>.<span class="title">springframework</span>.<span class="title">data</span>.<span class="title">redis</span>.<span class="title">connection</span>.<span class="title">RedisNode</span>&quot;&gt;</span><br><span class="line">                &lt;<span class="title">constructor</span>-<span class="title">arg</span> <span class="title">name</span>=&quot;<span class="title">host</span>&quot; <span class="title">value</span>=&quot;192.168.11.129&quot;&gt;&lt;/<span class="title">constructor</span>-<span class="title">arg</span>&gt;</span><br><span class="line">                &lt;<span class="title">constructor</span>-<span class="title">arg</span> <span class="title">name</span>=&quot;<span class="title">port</span>&quot; <span class="title">value</span>=&quot;26379&quot;&gt;&lt;/<span class="title">constructor</span>-<span class="title">arg</span>&gt;</span><br><span class="line">            &lt;/<span class="title">bean</span>&gt;</span><br><span class="line">            &lt;<span class="title">bean</span> <span class="title">class</span>=&quot;<span class="title">org</span>.<span class="title">springframework</span>.<span class="title">data</span>.<span class="title">redis</span>.<span class="title">connection</span>.<span class="title">RedisNode</span>&quot;&gt;</span><br><span class="line">                &lt;<span class="title">constructor</span>-<span class="title">arg</span> <span class="title">name</span>=&quot;<span class="title">host</span>&quot; <span class="title">value</span>=&quot;192.168.11.130&quot;&gt;&lt;/<span class="title">constructor</span>-<span class="title">arg</span>&gt;</span><br><span class="line">                &lt;<span class="title">constructor</span>-<span class="title">arg</span> <span class="title">name</span>=&quot;<span class="title">port</span>&quot; <span class="title">value</span>=&quot;26379&quot;&gt;&lt;/<span class="title">constructor</span>-<span class="title">arg</span>&gt;</span><br><span class="line">            &lt;/<span class="title">bean</span>&gt;</span><br><span class="line">        &lt;/<span class="title">set</span>&gt;</span><br><span class="line">    &lt;/<span class="title">property</span>&gt;</span><br><span class="line">&lt;/<span class="title">bean</span>&gt;</span><br></pre></td></tr></table></figure><h2 id="四、哨兵模式的其他配置项"><a href="#四、哨兵模式的其他配置项" class="headerlink" title="四、哨兵模式的其他配置项"></a>四、哨兵模式的其他配置项</h2><table><thead><tr><th>配置项</th><th>参数类型</th><th>作用</th></tr></thead><tbody><tr><td>port</td><td>整数</td><td>启动哨兵进程端口</td></tr><tr><td>dir</td><td>文件夹目录</td><td>哨兵进程服务临时文件夹，默认为/tmp，要保证有可写入的权限</td></tr><tr><td>sentinel down-after-milliseconds</td><td>&lt;服务名称&gt;&lt;毫秒数（整数）&gt;</td><td>指定哨兵在监控Redis服务时，当Redis服务在一个默认毫秒数内都无法回答时，单个哨兵认为的主观下线时间，默认为30000（30秒）</td></tr><tr><td>sentinel parallel-syncs</td><td>&lt;服务名称&gt;&lt;服务器数（整数）&gt;</td><td>指定可以有多少个Redis服务同步新的主机，一般而言，这个数字越小同步时间越长，而越大，则对网络资源要求越高</td></tr><tr><td>sentinel failover-timeout</td><td>&lt;服务名称&gt;&lt;毫秒数（整数）&gt;</td><td>指定故障切换允许的毫秒数，超过这个时间，就认为故障切换失败，默认为3分钟</td></tr><tr><td>sentinel notification-script</td><td>&lt;服务名称&gt;&lt;脚本路径&gt;</td><td>指定sentinel检测到该监控的redis实例指向的实例异常时，调用的报警脚本。该配置项可选，比较常用</td></tr></tbody></table><p>sentinel down-after-milliseconds配置项只是一个哨兵在超过规定时间依旧没有得到响应后，会自己认为主机不可用。对于其他哨兵而言，并不是这样认为。哨兵会记录这个消息，当拥有认为主观下线的哨兵达到sentinel monitor所配置的数量时，就会发起一次投票，进行failover，此时哨兵会重写Redis的哨兵配置文件，以适应新场景的需要。</p><blockquote><p>原文链接: <a href="https://www.jianshu.com/p/06ab9daf921d">https://www.jianshu.com/p/06ab9daf921d</a></p></blockquote>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Win10如何以管理员身份设置开机自启程序</title>
      <link href="linux/windows-start/"/>
      <url>linux/windows-start/</url>
      
        <content type="html"><![CDATA[<blockquote><p>转载</p></blockquote><p>自己水平太菜，对Windows的权限问题一直不是特别了解。之前在《Win10 如何以管理员身份设置开机自启程序(1)》一文中介绍了：通过Windows“任务计划程序”来实现以管理员身份开机自启。</p><p>但是，但是，遇到一台奇怪的Win10系统，上边的策略行不通。一旦设置管理员运行，就无法成功开机自启。而非管理员就可以正常自启。</p><p>后来瞎蒙出一种方法：</p><ul><li>(1) 对<strong>“A.exe”</strong>创建快捷方式<strong>“A.lnk”</strong></li><li>(2) 右键<strong>“A.lnk”</strong>-&gt; 高级，勾选用管理员身份运行；</li></ul><p> <img src= "/img/loading.gif" data-lazy-src="20170930131356710.png" alt="img"></p><ul><li>(3) 新建<strong>“A.bat”</strong>文件，将<strong>“A.lnk”</strong>的路径信息写入并保存，如：</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">@echo off</span><br><span class="line">&quot;C:\Users\ZFan\Desktop\A.lnk&quot;</span><br></pre></td></tr></table></figure><ul><li>(4) 打开<strong>“运行”</strong>输入<strong>“shell:startup”</strong>然后回车，然后将<strong>“A.bat”</strong>剪切到打开的目录中</li></ul><p><img src= "/img/loading.gif" data-lazy-src="1617198089460.png" alt="1617198089460"></p><p><img src= "/img/loading.gif" data-lazy-src="1617198110116.png" alt="1617198110116"></p><p> <img src= "/img/loading.gif" data-lazy-src="1617197997200.png" alt="1617197997200"></p><p>参考:</p><p>原文链接：<a href="https://blog.csdn.net/shuzfan/article/details/78141845">https://blog.csdn.net/shuzfan/article/details/78141845</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> Windows </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>gitbook添加valine评论功能</title>
      <link href="gitbook/comment/"/>
      <url>gitbook/comment/</url>
      
        <content type="html"><![CDATA[<blockquote><p>首先你需要获取appId和appKey</p></blockquote><p>可以参考<a href="https://valine.js.org/quickstart.html">https://valine.js.org/quickstart.html</a></p><p><img src= "/img/loading.gif" data-lazy-src="image-20210326140936833.png" alt="image-20210326140936833"></p><p><img src= "/img/loading.gif" data-lazy-src="image-20210326141024110.png" alt="image-20210326141024110"></p><p><img src= "/img/loading.gif" data-lazy-src="image-20210326141011256.png" alt="image-20210326141011256"></p><p><img src= "/img/loading.gif" data-lazy-src="image-20210326141048200.png" alt="image-20210326141048200"></p><p><img src= "/img/loading.gif" data-lazy-src="image-20210326141125850.png" alt="image-20210326141125850"></p><hr><p>在创建好应用后</p><p>在你的gitbook目录中,创建<code>book.json</code></p><p>添加内容到<code>book.json</code></p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">&quot;plugins&quot;</span>: [<span class="string">&quot;valine&quot;</span>],</span><br><span class="line">    <span class="attr">&quot;pluginsConfig&quot;</span>: &#123;</span><br><span class="line">        <span class="attr">&quot;valine&quot;</span>: &#123;</span><br><span class="line">            <span class="attr">&quot;appId&quot;</span>: <span class="string">&quot;your appId&quot;</span>,</span><br><span class="line">            <span class="attr">&quot;appKey&quot;</span>: <span class="string">&quot;your appKey&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>安装插件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitbook install ./</span><br></pre></td></tr></table></figure><p>接着可使用插件了，效果如下：</p><p><img src= "/img/loading.gif" data-lazy-src="image-20210326141326925.png" alt="image-20210326141326925"></p>]]></content>
      
      
      
        <tags>
            
            <tag> gitbook </tag>
            
            <tag> valine </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>CentOS7安装Graphite</title>
      <link href="operation/centos7-install-graphite/"/>
      <url>operation/centos7-install-graphite/</url>
      
        <content type="html"><![CDATA[<h2 id="Graphite简介"><a href="#Graphite简介" class="headerlink" title="Graphite简介"></a>Graphite简介</h2><p>Graphite是一个Python编写的企业级开源监控工具，采用django框架，用来收集服务器所有的即时状态，用户请求信息，Memcached命中率,RabbitMQ消息服务器的状态，操作系统的负载状态。</p><p>Graphite服务器大约每分钟需要有4800次的跟新操作，它采用简单的文本协议和绘图功能，可以方便的使用在任何操作系统上。</p><p>Graphite 自己本身并不收集具体的数据，这些数据收集的具体工作通常由第三方工具或插件完成（如 Ganglia, collectd, statsd, Collectl 等)。</p><h4 id="简单来说，Graphite主要做两件事情："><a href="#简单来说，Graphite主要做两件事情：" class="headerlink" title="简单来说，Graphite主要做两件事情："></a>简单来说，Graphite主要做两件事情：</h4><ul><li>实时监控第三方工具传来的数据</li><li>根据数据绘制图形</li></ul><h4 id="Graphite包含3个组件，carbon，whisper，graphite-webapp其中："><a href="#Graphite包含3个组件，carbon，whisper，graphite-webapp其中：" class="headerlink" title="Graphite包含3个组件，carbon，whisper，graphite webapp其中："></a>Graphite包含3个组件，carbon，whisper，graphite webapp其中：</h4><ul><li>carbon - 用于监控数据的 Twisted 守护进程</li><li>whisper - 用于存放和操作数据的库</li><li>graphite webapp - 用于绘制图形的Django webapp</li></ul><p>关于Graphite的详细官方文档可以参考<a href="http://graphite.readthedocs.io/en/latest/">Graphite Documentation</a></p><h2 id="Graphite安装"><a href="#Graphite安装" class="headerlink" title="Graphite安装"></a>Graphite安装</h2><p>我安装的环境是<code>CentOS 7</code>、<code>python 2.7.5</code></p><h4 id="1、修改yum源配置："><a href="#1、修改yum源配置：" class="headerlink" title="1、修改yum源配置："></a>1、修改yum源配置：</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">yum install wget</span><br><span class="line"></span><br><span class="line">mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> /etc/yum.repos.d/</span><br><span class="line"></span><br><span class="line">wget http://mirrors.163.com/.<span class="built_in">help</span>/CentOS6-Base-163.repo</span><br><span class="line"></span><br><span class="line">yum makecache</span><br><span class="line"></span><br><span class="line">yum -y update</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="2、安装pip、carbon-和whisper"><a href="#2、安装pip、carbon-和whisper" class="headerlink" title="2、安装pip、carbon 和whisper"></a>2、安装pip、carbon 和whisper</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">yum -y install epel-release   <span class="comment">#安装epel扩展源pip才能安装</span></span><br><span class="line">yum -y install python-pip</span><br><span class="line">yum -y install python-devel</span><br><span class="line">yum -y install gcc</span><br><span class="line">yum -y install unzip</span><br><span class="line">pip install carbon</span><br><span class="line">pip install whisper</span><br></pre></td></tr></table></figure><h4 id="3、安装graphite-web"><a href="#3、安装graphite-web" class="headerlink" title="3、安装graphite-web"></a>3、安装graphite-web</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">yum -y install libffi-devel zlib-devel openssl-devel install uwsgi-plugin-python</span><br><span class="line">pip install graphite-web</span><br><span class="line">pip uninstall django</span><br><span class="line">pip install django==1.8</span><br></pre></td></tr></table></figure><p>4、修改配置文件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /opt/graphite/conf/</span><br><span class="line">ls <span class="comment">#查看所有文件，拷贝去除example</span></span><br><span class="line">cp aggregation-rules.conf.example aggregation-rules.conf</span><br><span class="line">cp blacklist.conf.example blacklist.conf</span><br><span class="line">cp carbon.amqp.conf.example carbon.amqp.conf</span><br><span class="line">cp carbon.conf.example carbon.conf</span><br><span class="line">cp dashboard.conf.example dashboard.conf</span><br><span class="line">cp graphite.wsgi.example graphite.wsgi</span><br><span class="line">cp graphTemplates.conf.example graphTemplates.conf</span><br><span class="line">cp relay-rules.conf.example relay-rules.conf</span><br><span class="line">cp rewrite-rules.conf.example rewrite-rules.conf</span><br><span class="line">cp storage-aggregation.conf.example storage-aggregation.conf</span><br><span class="line">cp storage-schemas.conf.example storage-schemas.conf</span><br><span class="line">cp whitelist.conf.example whitelist.conf</span><br><span class="line"><span class="built_in">cd</span> /opt/graphite/webapp/graphite</span><br><span class="line">cp local_settings.py.example local_settings.py</span><br><span class="line"><span class="built_in">cd</span> ../</span><br><span class="line">mv content static</span><br><span class="line">vi uwsgi.ini</span><br></pre></td></tr></table></figure><p>拷贝如下代码进去，保存退出</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">[uwsgi]</span><br><span class="line"><span class="comment"># Django-related settings</span></span><br><span class="line"></span><br><span class="line">socket = :8000</span><br><span class="line"></span><br><span class="line">buffer-size = 40000</span><br><span class="line"></span><br><span class="line">plugins=python</span><br><span class="line"><span class="comment"># the base directory (full path)</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">chdir</span> = /opt/graphite/webapp</span><br><span class="line"></span><br><span class="line"><span class="comment"># Django s wsgi file</span></span><br><span class="line"></span><br><span class="line">module = graphite.wsgi</span><br><span class="line"></span><br><span class="line"><span class="comment"># process-related settings</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># master</span></span><br><span class="line"></span><br><span class="line">master = <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># maximum number of worker processes</span></span><br><span class="line"></span><br><span class="line">processes = 1</span><br><span class="line"></span><br><span class="line"><span class="comment"># ... with appropriate permissions - may be needed</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># chmod-socket = 664</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># clear environment on exit</span></span><br><span class="line"></span><br><span class="line">vacuum = <span class="literal">true</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="5、安装uwsgi和nginx"><a href="#5、安装uwsgi和nginx" class="headerlink" title="5、安装uwsgi和nginx"></a>5、安装uwsgi和nginx</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">yum -y install uwsgi</span><br><span class="line">cd &#x2F;home&#x2F;admin&#x2F;</span><br><span class="line">wget http:&#x2F;&#x2F;nginx.org&#x2F;download&#x2F;nginx-1.4.7.tar.gz</span><br><span class="line">tar zxvf nginx-1.4.7.tar.gz</span><br><span class="line">cd nginx-1.4.7</span><br><span class="line">.&#x2F;configure --with-openssl&#x3D;&#x2F;usr&#x2F;include&#x2F;openssl</span><br><span class="line">vi objs&#x2F;Makefile   #把第3行的“ -Werror ” 删除，保存，关闭</span><br><span class="line">make</span><br><span class="line">make install</span><br><span class="line">vi &#x2F;usr&#x2F;local&#x2F;nginx&#x2F;conf&#x2F;nginx.conf</span><br></pre></td></tr></table></figure><p>拷贝如下代码进去，保存退出</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">user  root;</span><br><span class="line"></span><br><span class="line">worker_processes  1;</span><br><span class="line"></span><br><span class="line"><span class="comment">#error_log  logs/error.log;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#error_log  logs/error.log  notice;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#error_log  logs/error.log  info;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#pid        logs/nginx.pid;</span></span><br><span class="line"></span><br><span class="line">events &#123;</span><br><span class="line"></span><br><span class="line">    worker_connections  1024;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">http &#123;</span><br><span class="line"></span><br><span class="line">    include       mime.types;</span><br><span class="line"></span><br><span class="line">    default_type  application/octet-stream;</span><br><span class="line"></span><br><span class="line">    sendfile        on;</span><br><span class="line"></span><br><span class="line">    keepalive_timeout  65;</span><br><span class="line"></span><br><span class="line">    server &#123;</span><br><span class="line"></span><br><span class="line">        listen       8001;</span><br><span class="line"></span><br><span class="line">        server_name  localhost;</span><br><span class="line"></span><br><span class="line">        charset     utf-8;</span><br><span class="line"></span><br><span class="line">        <span class="comment">#access_log  logs/host.access.log  main;</span></span><br><span class="line"></span><br><span class="line">        location / &#123;</span><br><span class="line"></span><br><span class="line">            include uwsgi_params;</span><br><span class="line"></span><br><span class="line">            uwsgi_pass 127.0.0.1:8000;</span><br><span class="line"></span><br><span class="line">             uwsgi_read_timeout 2;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        location /static &#123;</span><br><span class="line"></span><br><span class="line">            root  /opt/graphite/webapp;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="6、在网站上找到项目，创建manage-py，好进行数据库的操作，和测试显示项目中的问题"><a href="#6、在网站上找到项目，创建manage-py，好进行数据库的操作，和测试显示项目中的问题" class="headerlink" title="6、在网站上找到项目，创建manage.py，好进行数据库的操作，和测试显示项目中的问题"></a>6、在网站上找到项目，创建<code>manage.py</code>，好进行数据库的操作，和测试显示项目中的问题</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /opt/graphite/webapp/</span><br><span class="line">vi manage.py </span><br></pre></td></tr></table></figure><p>拷贝如下代码进去，保存退出</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">     os.environ.setdefault(<span class="string">&quot;DJANGO_SETTINGS_MODULE&quot;</span>, <span class="string">&quot;graphite.settings&quot;</span>)</span><br><span class="line">     <span class="keyword">from</span> django.core.management <span class="keyword">import</span> execute_from_command_line</span><br><span class="line">     execute_from_command_line(sys.argv)</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">pip install scandir</span><br><span class="line">python manage.py migrate</span><br><span class="line">vi /opt/graphite/webapp/graphite/local_settings.py</span><br><span class="line"><span class="comment">#取消SECRET_KEY、TIME_ZONE注释，并且修改值：</span></span><br><span class="line">SECRET_KEY = <span class="string">&#x27;@2o8&amp;38gcsb(p*o*dy(fmh!_3-30a1qwq$sadb+6vk243%wj0#&#x27;</span></span><br><span class="line">TIME_ZONE = <span class="string">&#x27;Asia/Shanghai&#x27;</span></span><br><span class="line"><span class="comment">#保存退出</span></span><br></pre></td></tr></table></figure><h4 id="7、通过manage-py-shell修改网站登录的用户名和密码"><a href="#7、通过manage-py-shell修改网站登录的用户名和密码" class="headerlink" title="7、通过manage.py shell修改网站登录的用户名和密码"></a>7、通过manage.py shell修改网站登录的用户名和密码</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">python manage.py shell</span><br><span class="line">&gt;&gt;&gt; from django.contrib.auth.models import User</span><br><span class="line">&gt;&gt;&gt; user_list=[x <span class="keyword">for</span> x <span class="keyword">in</span> User.objects.all()]</span><br><span class="line">&gt;&gt;&gt; <span class="built_in">print</span> user_list</span><br><span class="line"><span class="comment">#如果user_list不为空</span></span><br><span class="line">&gt;&gt;&gt;user=user_list[0]</span><br><span class="line">&gt;&gt;&gt;user.username=<span class="string">&#x27;admin&#x27;</span></span><br><span class="line">&gt;&gt;&gt;user.set_password=<span class="string">&#x27;123123&#x27;</span></span><br><span class="line">&gt;&gt;&gt;user.save()</span><br><span class="line"><span class="comment">#如果user_list为空</span></span><br><span class="line">&gt;&gt;&gt;quit()</span><br><span class="line">python manage.py createsuperuser</span><br><span class="line"><span class="comment">#根据提示创建你的用户</span></span><br><span class="line">Username (leave blank to use <span class="string">&#x27;root&#x27;</span>): admin</span><br><span class="line">Email address: 123123@qq.com</span><br><span class="line">Password:     <span class="comment">#输入后不会显示，我输的123123</span></span><br><span class="line">Password (again):     <span class="comment">#输入后不会显示</span></span><br></pre></td></tr></table></figure><h4 id="8、启动carbon，carbon会在默认的2003端口接收数据。"><a href="#8、启动carbon，carbon会在默认的2003端口接收数据。" class="headerlink" title="8、启动carbon，carbon会在默认的2003端口接收数据。"></a>8、启动carbon，carbon会在默认的2003端口接收数据。</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">python /opt/graphite/bin/carbon-cache.py start</span><br><span class="line">uwsgi --ini /opt/graphite/webapp/uwsgi.ini </span><br><span class="line"><span class="comment">#再新建一个窗口，启动nginx，或者让uwsgi后台运行，建议测试的时候新建窗口，错误好捕获。启动nginx之前，先关闭防火墙或者开启8001端口。我做测试，就关闭防火墙了。</span></span><br><span class="line">systemctl <span class="built_in">disable</span> firewalld <span class="comment">#停用防火墙</span></span><br><span class="line">systemctl stop firewalld    <span class="comment">#禁止防火墙</span></span><br><span class="line">/usr/<span class="built_in">local</span>/nginx/sbin/nginx           <span class="comment">#启动nginx</span></span><br><span class="line">/usr/<span class="built_in">local</span>/nginx/sbin/nginx -s reload   <span class="comment">#重启nginx</span></span><br></pre></td></tr></table></figure><h4 id="9、浏览"><a href="#9、浏览" class="headerlink" title="9、浏览"></a>9、浏览</h4><p>网址<a href="http://127.0.0.1:8001，出现如下画面，安装成功，如果失败，注意查看nginx的错误日志和uwsgi的提示">http://127.0.0.1:8001，出现如下画面，安装成功，如果失败，注意查看nginx的错误日志和uwsgi的提示</a></p><p><img src= "/img/loading.gif" data-lazy-src="14.png"></p><p>参考：<a href="http://tripleday.cn/2016/10/06/graphite/">http://tripleday.cn/2016/10/06/graphite/</a></p><p>转载于:</p><p><a href="https://blog.csdn.net/aigu1989/article/details/102241677">https://blog.csdn.net/aigu1989/article/details/102241677</a></p><p><a href="https://www.cnblogs.com/zhang-ke/p/6878511.html">https://www.cnblogs.com/zhang-ke/p/6878511.html</a></p><hr><h1 id="官方文檔"><a href="#官方文檔" class="headerlink" title="官方文檔"></a>官方文檔</h1><p>翻译从<a href="https://graphite.readthedocs.io/en/latest/overview.html">这里</a></p><h1 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h1><h2 id="Graphite能做什么和不能做什么"><a href="#Graphite能做什么和不能做什么" class="headerlink" title="Graphite能做什么和不能做什么"></a>Graphite能做什么和不能做什么</h2><p>Graphite可以做下面两件事情</p><ol><li>存储 时间戳 数据</li><li>按照你的需求渲染数据到图</li></ol><p>Graphite不能够帮你搜集数据,然后下面这些工具 <a href="https://graphite.readthedocs.io/en/latest/tools.html">tools</a> 可以发送数据到Graphite</p><p>尽管这通常需要一点代码，</p><p><a href="https://graphite.readthedocs.io/en/latest/feeding-carbon.html">sending data</a> 发送数据到Graphite是很容易的</p><h2 id="关于项目"><a href="#关于项目" class="headerlink" title="关于项目"></a>关于项目</h2><blockquote><p>Graphite是一个企业级的监控工具,并且能够运行在你的便宜的机器上.</p></blockquote><p>2006的时候,他被 <a href="mailto:chrismd%40gmail.com">Chris Davis</a> 在 <a href="http://www.orbitz.com/">Orbitz</a> 设计出来的,当时是作为一个</p><blockquote><p>副项目，它最终成长为一个基本的监控工具。</p></blockquote><p>2008年，Orbitz允许在开源Apache 2.0许可下发布Graphite。从那以后，克里斯继续致力于Graphite的研究，并将其应用于包括 <a href="http://www.sears.com/">Sears</a>在内的其他公司,它在这里作为电子商务监控系统的支柱.</p><p>到了今天,更多的<a href="https://graphite.readthedocs.io/en/latest/who-is-using.html">公司</a> 在用它</p><h2 id="架构概述"><a href="#架构概述" class="headerlink" title="架构概述"></a>架构概述</h2><p>Graphite由3个软件组件组成:</p><ul><li>carbon-一个侦听时间序列数据的进程</li><li>whisper - 一个时间序列数据的数据库(和RRD比较相似)</li><li>graphite webapp - 一个<a href="http://victorfengming.gitee.io/course/django/">django</a>项目,它使用Cairo按需渲染图形</li></ul><blockquote><p>输入数据非常简单，通常大多数工作都是在一开始收集数据.</p></blockquote><p>随着你发送数据点到carbon,他们马上就可用了,提供一个图形的web app.</p><blockquote><p>这个webapp 通过几种方式去创建和展示图形(包括简单呐的urlapi)来渲染并且使它很容易嵌入图形在其他网页。</p></blockquote><h2 id="Graphite-是啥"><a href="#Graphite-是啥" class="headerlink" title="Graphite 是啥"></a>Graphite 是啥</h2><p>他是一个高度可扩展的实时绘图系统.作为一个用户,你编写一个 能够收集数字时间序列数据 的应用,并且收集你感兴趣的图形,然后发送到Graphite一个后端的进程, carbon, 他能够存储这个数据在 Graphite的专门的数据库中. 这个数据能够 通过 Graphite的网络接口可视化.</p><h2 id="什么样的牛马能用这个Graphite"><a href="#什么样的牛马能用这个Graphite" class="headerlink" title="什么样的牛马能用这个Graphite"></a>什么样的牛马能用这个Graphite</h2><blockquote><p>任何想要跟踪任何东西的值的人都成.如果你有一个能潜在的伴随时间改变的值,并且你可能想要用图来表达,那么Graphite可能可以满足你的需求哦.</p></blockquote><p>说白了,Graphite被设计就是为了处理这种数字时间序列数据.</p><blockquote><p>举个栗子,Graphite擅长 画这个 股票价格图,因为他们的值是随着时间而改变的.</p></blockquote><p>无论是几个数据点,或者来自数千台服务器的几十个性能指标，那么Graphite就适合您了。</p><blockquote><p>另外，您不必提前知道这些东西的名字(谁想维护这么大的配置?)</p></blockquote><p>您只需发送一个度量名称、一个时间戳和一个值，Graphite将负责其余的工作!</p><h2 id="Graphite的可扩展性咋样"><a href="#Graphite的可扩展性咋样" class="headerlink" title="Graphite的可扩展性咋样?"></a>Graphite的可扩展性咋样?</h2><p>从CPU的角度来说,Graphite在前端和后端水平扩展，这意味着您可以简单地添加更多的机器来获得更多的吞吐量.</p><blockquote><p>它还具有容错性，因为丢失后端机器将导致最小数量的数据丢失(该机器在内存中缓存的任何数据)，并且如果您有足够的剩余容量来处理负载，则不会破坏系统</p></blockquote><p>从I/O的角度说,在负载下，Graphite在许多不同的文件上非常快速地执行许多微小的I/O操作. 这是因为发送给Graphite的每一个不同的指标都被存储到了他自己的数据库文件中,这与很多构建在RRD上面的工具 (drraw, Cacti, Centreon, etc) 相似.</p><blockquote><p>在事实上,Graphite最初确实使用RRD来存储，直到出现了根本性的限制，需要一种新的存储引擎</p></blockquote><p>高容量(每分钟更新几千个不同的度量)几乎需要一个好的RAID阵列和/或ssd。如果磁盘不能跟上大量的小的写操作(每个数据点只有几个字节，但是大多数标准磁盘每秒不能做超过几千个I/O操作，即使它们很小)，那么Graphite的后端缓存传入的数据。当这种情况发生时，Graphite的数据库引擎whisper允许carbon一次写入多个数据点，从而只以将多余的数据缓存在内存中直到可以写入为代价来提高总体吞吐量。</p><p>Graphite还支持<a href="https://graphite.readthedocs.io/en/latest/storage-backends.html">可替代的存储后端</a> ，可以极大地改变这些特性。</p><h2 id="这个图表的实时性咋样"><a href="#这个图表的实时性咋样" class="headerlink" title="这个图表的实时性咋样?"></a>这个图表的实时性咋样?</h2><blockquote><p>非常牛逼,甚至在高负荷的情况下,在每个时间间隔的数量指标来远远大于你的存储系统可以执行I / O操作和大量的数据被缓存在存储管道(见以前的问题的解释),Graphite仍然吸引了实时图表。</p></blockquote><p>诀窍在于,当Graphitewebapp接收请求画一个图,它同时检索数据以及从贮前缓存从磁盘(可能是分布式的如果你有多个后端服务器),结合数据来创建一个实时图的两个来源。</p><h2 id="都谁已经用这个Graphite"><a href="#都谁已经用这个Graphite" class="headerlink" title="都谁已经用这个Graphite"></a>都谁已经用这个Graphite</h2><blockquote><p>Graphite是Orbitz内部开发的，用于可视化各种操作——关键数据，包括应用程序指标、数据库指标、销售等。</p></blockquote><p>在撰写本文时，Orbitz的生产系统在一个非常快的SAN上的两台niagra-2 Sun服务器上运行时，每分钟可以处理大约16万个不同的指标。</p><h2 id="Graphite是啥写的"><a href="#Graphite是啥写的" class="headerlink" title="Graphite是啥写的"></a>Graphite是啥写的</h2><p>Python2写的,Graphite webapp建立在Django web框架上，使用ExtJS javascript GUI工具包。图形呈现是使用Cairo图形库完成的。后端和数据库是用纯Python编写的。</p><h2 id="哪位大神开发并维护的Graphite"><a href="#哪位大神开发并维护的Graphite" class="headerlink" title="哪位大神开发并维护的Graphite"></a>哪位大神开发并维护的Graphite</h2><blockquote><p>Graphite最初是由Chris Davis在Orbitz开发的。Orbitz长期以来一直是开源社区的一部分，并发布了其他一些内部开发的产品。</p></blockquote><p>Graphite目前是由一个志愿者团队开发的石墨项目GitHub组织</p><p>说白了,就是开源的</p><h2 id="Graphite用没用到RRDtool"><a href="#Graphite用没用到RRDtool" class="headerlink" title="Graphite用没用到RRDtool"></a>Graphite用没用到RRDtool</h2><blockquote><p>不，至少从2006年Graphite首次问世以来就没有了</p></blockquote><p>Graphite有自己专门的数据库库whisper，它在设计上与RRD非常相似，但有一个Graphite所需要的细微但根本重要的区别。创建whisper有两个原因。</p><blockquote><p>第一个原因是，RRD是在这样的假设下设计的，即数据总是会定期地插入到数据库中，而这种假设会导致RRD在给出不定期出现的数据时表现出不受欢迎的行为。</p></blockquote><p>创建Graphite是为了方便各种应用程序指标的可视化，这些指标并不总是经常发生，比如当处理一个不常见的请求时，测量延迟并发送给Graphite。</p><blockquote><p>使用RRD，数据被放置到数据库内的一个临时区域中，直到当前时间间隔已通过，才可以访问该区域，并在接下来的时间间隔内将另一个值插入到数据库中。</p></blockquote><p>如果在指定的时间内没有发生这种情况，原始数据点将被覆盖并丢失。现在对于一些指标来说，缺少值可以被正确地解释为0，但是对于延迟等指标则不是这样，因为0表示工作是在0时间内完成的，这与没有工作是不同的。假设延迟为零也会破坏分析，如计算平均延迟等。</p><p>编写whisper的第二个原因是性能。</p><blockquote><p>RRDtool非常快;事实上，它比耳语快得多。</p></blockquote><p>但是RRD(在编写whisper时)的问题是，RRD一次只允许向数据库插入单个值，而编写whisper则允许一次插入多个数据点，将它们压缩到单个写操作中。</p><blockquote><p>这极大地提高了在高负载下的性能，因为Graphite操作的是很多很多的文件，而对于这样小的操作(写一些字节在这里，写一些字节在那里，等等)，瓶颈是由I/O操作的数量造成的。</p></blockquote><p>考虑这样一个场景，Graphite每分钟接收100000个不同的公制值;为了维持这种负载，Graphite必须能够每分钟向磁盘写入这么多的数据点。但假设底层存储每分钟只能处理20,000个I/O操作。</p><blockquote><p>有了RRD(写whisper的时候)，就没有机会跟上了。</p></blockquote><p>但是对于whisper，我们可以一直缓存传入的数据，直到我们为一个给定的度量积累了10分钟的数据，然后不用做10个I/O操作来写这10个数据点，whisper可以在一个操作中完成。</p><blockquote><p>我一直提到“在编写whisper时”的原因是RRD现在支持这种行为。然而，只要第一个问题仍然存在，Graphite就会继续使用whisper。</p></blockquote><h2 id="Graphite的结构图"><a href="#Graphite的结构图" class="headerlink" title="Graphite的结构图"></a>Graphite的结构图</h2><h2 id=""><a href="#" class="headerlink" title=""></a><img src= "/img/loading.gif" data-lazy-src="overview.png"></h2><p>暂时翻译到这里,如需阅读更多在 <a href="https://graphite.readthedocs.io/en/latest/install.html">这里</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> graphite </tag>
            
            <tag> centos </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>collectd官方教程翻译</title>
      <link href="operation/collectd-official-translate/"/>
      <url>operation/collectd-official-translate/</url>
      
        <content type="html"><![CDATA[<p><a href="https://collectd.org/wiki/index.php/First_steps">官方文档地址</a></p><h2 id="1-下载官方压缩包"><a href="#1-下载官方压缩包" class="headerlink" title="1.下载官方压缩包"></a>1.下载官方压缩包</h2><ol><li><p>你可以通过,<a href="https://collectd.org/download.shtml">官方地址</a> 下载</p></li><li><p>也可以通过命令下载</p></li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /tmp/</span><br><span class="line">wget http://collectd.org/files/collectd-x.y.z.tar.bz2</span><br><span class="line">tar jxf collectd-x.y.z.tar.bz2</span><br><span class="line"><span class="built_in">cd</span> collectd-x.y.z</span><br></pre></td></tr></table></figure><h2 id="2-现在用常规配置来配置源文件"><a href="#2-现在用常规配置来配置源文件" class="headerlink" title="2.现在用常规配置来配置源文件"></a>2.现在用常规配置来配置源文件</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./configure </span><br></pre></td></tr></table></figure><p>完成<code>configure</code>脚本后，它会显示它找到(和没有找到)的库的摘要，以及哪些插件已经启用。</p><p>默认情况下，满足依赖关系的所有插件都是启用的。如果您想使用的插件缺失，请安装所需的开发包并再次运行<code>configure</code>。</p><p>最后但并非最不重要的:编译并安装程序。默认情况下，它将安装到<code>/opt/collectd</code>。如果您更喜欢另一个目录，可以使用<code>——prefix</code>选项调用configure脚本。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">make all install</span><br><span class="line"><span class="built_in">cd</span> /opt/collectd/</span><br></pre></td></tr></table></figure><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><p>配置文件在<code>/etc/collectd.conf</code>中。<code>&lt;/prefix&gt;</code>手册页<a href="http://collectd.org/documentation/manpages/collectd.conf.5.shtml">collectd.conf</a>。打开文件并特别注意<code>LoadPlugin</code>行。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim etc/collectd.conf</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> collectd </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>collectd+graphite使用</title>
      <link href="operation/collectd-use/"/>
      <url>operation/collectd-use/</url>
      
        <content type="html"><![CDATA[<h2 id="collectd和graphite是用来做什么的"><a href="#collectd和graphite是用来做什么的" class="headerlink" title="collectd和graphite是用来做什么的"></a>collectd和graphite是用来做什么的</h2><ul><li>collectd: 是一个守护(daemon)进程，用来收集系统性能和提供各种存储方式来存储不同值的机制。比如基本的系统性能的收集（CPU、memory、process等）</li><li>graphite：是一个企业级的监控工具，可以在廉价机硬件上运行；Graphite仅是一个画图工具，不主动地收集数据，而是将接收到的数据以图形的方式展现出来。</li></ul><p> 这里结合collectd和graphite，collectd用于收集数据，graphite以图表的形式显示数据 </p><h3 id="collect安装"><a href="#collect安装" class="headerlink" title="collect安装"></a>collect安装</h3><ul><li>安装collectd-5.5.0.tar.gz，这个是目前最新版本，对java等支持非常好</li><li>在root@10.175.180.180这台机：<ul><li>安装包在/tmp目录下，将其解压安装</li><li>安装完在/etc目录下有份collectd.conf配置文件，在其中配置需要的即可</li><li>启动命令：service collectd restart/start</li></ul></li></ul><p> install process: </p><ol><li>Install prereqs</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum -y install libcurl libcurl-devel rrdtool rrdtool-devel rrdtool-prel libgcrypt-devel gcc make gcc-c++</span><br></pre></td></tr></table></figure><ol start="2"><li> Get Collectd, untar it, make it and install </li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">wget http://collectd.org/files/collectd-5.5.0.tar.gz</span><br><span class="line"></span><br><span class="line">tar zxvf collectd-5.5.0.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> collectd-5.5.0</span><br><span class="line"></span><br><span class="line">./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=/usr/lib --mandir=/usr/share/man --enable-all-plugins</span><br><span class="line"></span><br><span class="line">make</span><br><span class="line"></span><br><span class="line">make install</span><br></pre></td></tr></table></figure><ol start="3"><li>Copy the default init.d script </li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cp /tmp/collectd-5.4.0/contrib/redhat/init.d-collectd /etc/init.d/collectd</span><br></pre></td></tr></table></figure><ol start="4"><li> Set the correct permissions </li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chmod +x /etc/init.d/collectd</span><br></pre></td></tr></table></figure><ol start="5"><li>Start the deamon</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">service collectd start</span><br></pre></td></tr></table></figure><p> Note:If cannot tar the <code>collectd-5.5.0.tar.gz</code>, you should upload it. </p><h3 id="graphite安装"><a href="#graphite安装" class="headerlink" title="graphite安装"></a>graphite安装</h3><p>这里不介绍graphite的安装，本人没有安装graphite，在配置的Linux上已经安装好了graphite，就不误导大家了。推荐大家浏览</p><p> <a href="http://my.oschina.net/fufangchun/blog/232895?p=1">http://my.oschina.net/fufangchun/blog/232895?p=1</a> </p><p> 这里有详细的原理、安装等说明 </p><h3 id="collectd-conf基本配置"><a href="#collectd-conf基本配置" class="headerlink" title="collectd.conf基本配置"></a>collectd.conf基本配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">###########################################################</span></span><br><span class="line"><span class="comment">##############################################################################</span></span><br><span class="line"><span class="comment"># Global                                                                     #</span></span><br><span class="line"><span class="comment">#----------------------------------------------------------------------------#</span></span><br><span class="line"><span class="comment"># Global settings for the daemon.                                            #</span></span><br><span class="line"><span class="comment">##############################################################################</span></span><br><span class="line"></span><br><span class="line">Hostname    <span class="string">&quot;localhost&quot;</span></span><br><span class="line"><span class="comment">#FQDNLookup   true</span></span><br><span class="line"><span class="comment">#BaseDir     &quot;/var/lib/collectd&quot;</span></span><br><span class="line"><span class="comment">#PIDFile     &quot;/var/run/collectd.pid&quot;</span></span><br><span class="line"><span class="comment">#PluginDir   &quot;/usr/lib/collectd&quot;</span></span><br><span class="line"><span class="comment">#TypesDB     &quot;/usr/share/collectd/types.db&quot;</span></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#----------------------------------------------------------------------------#</span></span><br><span class="line"><span class="comment"># Interval at which to query values. This may be overwritten on a per-plugin #</span></span><br><span class="line"><span class="comment"># base by using the &#x27;Interval&#x27; option of the LoadPlugin block:               #</span></span><br><span class="line"><span class="comment">#   &lt;LoadPlugin foo&gt;                                                         #</span></span><br><span class="line"><span class="comment">#       Interval 60                                                          #</span></span><br><span class="line"><span class="comment">#   &lt;/LoadPlugin&gt;                                                            #</span></span><br><span class="line"><span class="comment">#----------------------------------------------------------------------------#</span></span><br><span class="line"></span><br><span class="line">&lt;LoadPlugin write_graphite&gt;</span><br><span class="line">  Interval 5</span><br><span class="line">&lt;/LoadPlugin&gt;</span><br><span class="line"></span><br><span class="line">Interval     10</span><br><span class="line">Timeout      2</span><br><span class="line">ReadThreads  5</span><br><span class="line">WriteThreads 5</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">##############################################################################</span></span><br><span class="line"><span class="comment"># Logging                                                                    #</span></span><br><span class="line"><span class="comment">#----------------------------------------------------------------------------#</span></span><br><span class="line"><span class="comment"># Plugins which provide logging functions should be loaded first, so log     #</span></span><br><span class="line"><span class="comment"># messages generated when loading or configuring other plugins can be        #</span></span><br><span class="line"><span class="comment"># accessed.                                                                  #</span></span><br><span class="line"><span class="comment">##############################################################################</span></span><br><span class="line"></span><br><span class="line">LoadPlugin syslog</span><br><span class="line">LoadPlugin logfile</span><br><span class="line"></span><br><span class="line">&lt;Plugin logfile&gt;</span><br><span class="line">LogLevel info</span><br><span class="line">File STDOUT</span><br><span class="line">Timestamp <span class="literal">true</span></span><br><span class="line">PrintSeverity <span class="literal">false</span></span><br><span class="line">&lt;/Plugin&gt;</span><br><span class="line"></span><br><span class="line">&lt;Plugin syslog&gt;</span><br><span class="line">LogLevel info</span><br><span class="line">&lt;/Plugin&gt;</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">##############################################################################</span></span><br><span class="line"><span class="comment"># LoadPlugin section                                                         #</span></span><br><span class="line"><span class="comment">#----------------------------------------------------------------------------#</span></span><br><span class="line"><span class="comment"># Lines beginning with a single `#&#x27; belong to plugins which have been built  #</span></span><br><span class="line"><span class="comment"># but are disabled by default.                                               #</span></span><br><span class="line"><span class="comment">#                                                                            #</span></span><br><span class="line"><span class="comment"># Lines begnning with `##&#x27; belong to plugins which have not been built due   #</span></span><br><span class="line"><span class="comment"># to missing dependencies or because they have been deactivated explicitly.  #</span></span><br><span class="line"><span class="comment">##############################################################################</span></span><br><span class="line"></span><br><span class="line">LoadPlugin cpu</span><br><span class="line">LoadPlugin interface</span><br><span class="line">LoadPlugin memory</span><br><span class="line">LoadPlugin processes</span><br><span class="line">LoadPlugin users</span><br><span class="line">LoadPlugin disk</span><br><span class="line">LoadPlugin java</span><br><span class="line">LoadPlugin write_graphite</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">##############################################################################</span></span><br><span class="line"><span class="comment"># Plugin configuration                                                       #</span></span><br><span class="line"><span class="comment">#----------------------------------------------------------------------------#</span></span><br><span class="line"><span class="comment"># In this section configuration stubs for each plugin are provided. A desc-  #</span></span><br><span class="line"><span class="comment"># ription of those options is available in the collectd.conf(5) manual page. #</span></span><br><span class="line"><span class="comment">##############################################################################</span></span><br><span class="line"></span><br><span class="line">&lt;Plugin disk&gt;</span><br><span class="line">        Disk <span class="string">&quot;/^[vhs]d[a-f][0-9]?$/&quot;</span></span><br><span class="line">        IgnoreSelected <span class="literal">false</span></span><br><span class="line">&lt;/Plugin&gt;</span><br><span class="line"></span><br><span class="line">&lt;Plugin interface&gt;</span><br><span class="line">        Interface <span class="string">&quot;eth0&quot;</span></span><br><span class="line">        IgnoreSelected <span class="literal">false</span></span><br><span class="line">&lt;/Plugin&gt;</span><br><span class="line"></span><br><span class="line">&lt;Plugin  write_graphite&gt;</span><br><span class="line">    &lt;Node <span class="string">&quot;graphing&quot;</span>&gt;</span><br><span class="line">        Host <span class="string">&quot;localhost&quot;</span></span><br><span class="line">        Port <span class="string">&quot;2003&quot;</span></span><br><span class="line">        Protocol <span class="string">&quot;tcp&quot;</span></span><br><span class="line">        LogSendErrors <span class="literal">true</span></span><br><span class="line">        Prefix <span class="string">&quot;collectd.&quot;</span></span><br><span class="line">        StoreRates <span class="literal">true</span></span><br><span class="line">        AlwaysAppendDS <span class="literal">false</span></span><br><span class="line">        EscapeCharacter <span class="string">&quot;_&quot;</span></span><br><span class="line">    &lt;/Node&gt;</span><br><span class="line">&lt;/Plugin&gt;</span><br></pre></td></tr></table></figure><h3 id="graphite显示的结果"><a href="#graphite显示的结果" class="headerlink" title="graphite显示的结果"></a>graphite显示的结果</h3><p> <img src= "/img/loading.gif" data-lazy-src="20160113172857144" alt="这里写图片描述"> </p>]]></content>
      
      
      
    </entry>
    
    
    
    <entry>
      <title>如何安装和配置“Collectd”和“Collectd-Web”以监控Linux中的服务器资源</title>
      <link href="operation/install-collectd/"/>
      <url>operation/install-collectd/</url>
      
        <content type="html"><![CDATA[<p><img src= "/img/loading.gif" data-lazy-src="workbench.jpg" alt="img"> </p><h2 id="如何安装和配置“Collectd”和“Collectd-Web”以监控Linux中的服务器资源"><a href="#如何安装和配置“Collectd”和“Collectd-Web”以监控Linux中的服务器资源" class="headerlink" title="如何安装和配置“Collectd”和“Collectd-Web”以监控Linux中的服务器资源"></a>如何安装和配置“Collectd”和“Collectd-Web”以监控Linux中的服务器资源</h2><p>本教程将介绍在RHEL / CentOS / Fedora和基于Ubuntu / Debian的系统上的Collectd和Collectd-web界面的安装过程，</p><p>分类:<a href="https://www.howtoing.com/category/monitoring-tools">监控工具</a><a href="https://www.howtoing.com/category/developer-kits">开发工具</a></p><p> <em>2015-06-30 00:00:00</em></p><p><strong>Collectd的Web</strong>是基于RRDtool的<strong>（R</strong> ound- <strong>- [R</strong> <strong>obinÐatabase</strong> <strong>工具），</strong>它解释和图形输出，通过在Linux系统上<strong>Collectd</strong>服务收集的数据的Web前端监控工具。</p><p><strong>Collectd</strong>服务需要在默认情况下可用插件的巨大集合到其默认的配置文件，其中一些被默认情况下，已激活，一旦你已经安装了软件包。</p><p><strong>Collectd卷材CGI</strong>脚本它解释，并生成图形html页面统计数据可以由<strong>Apache CGI</strong>网关以最小的Apache Web服务器侧需要配置简单地执行。</p><p>然而，随着生成的统计图形Web界面可以，还可以通过自带预装与主<strong>Git</strong>仓库被<strong>Python</strong>脚本<strong>CGIHTTPServer</strong>提供的独立的Web服务器执行。</p><p>本教程将介绍<strong>Collectd</strong>服务和<strong>Collectd-Web</strong>界面<strong>RHEL / CentOS的/ Fedora</strong>和<strong>Ubuntu / Debian的</strong>基于系统的需要的，以便运行服务，并启用<strong>Collectd</strong>服务插件做的最小配置的安装过程。</p><p>请通过<strong>collectd</strong>系列的以下文章。</p><p><strong>第1部分</strong> ： <strong>安装和配置“Collectd’和’Collectd的Web”监视Linux的资源</strong></p><p><strong>第2部分</strong> ： <a href="https://www.howtoing.com/monitor-linux-server-resources-with-collectd-web-and-apache-cgi/">监控Linux的资源与Collectd的Web和Apache CGI</a></p><p><strong>第3部分</strong> ： <a href="https://www.howtoing.com/configure-collectd-as-central-monitoring-server-for-clients/">配置Collectd作为中央监控服务器的客户端</a></p><h3 id="第1步：-安装Collectd服务"><a href="#第1步：-安装Collectd服务" class="headerlink" title="第1步： - 安装Collectd服务"></a>第1步： - 安装Collectd服务</h3><p><strong>1.<strong>基本上</strong>，Collectd</strong>守护任务是收集和存储数据的统计，它运行在系统上。 该<strong>Collectd</strong>包可以下载并安装由发出以下命令的默认基于Debian发行库：</p><h5 id="在Ubuntu-Debian"><a href="#在Ubuntu-Debian" class="headerlink" title="在Ubuntu / Debian"></a>在Ubuntu / Debian</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"># apt-get install collectd[On Debian based Systems]</span><br></pre></td></tr></table></figure><p><a href="https://www.howtoing.com/wp-content/uploads/2015/04/Install-Collectd-on-Ubuntu-568x450.png"><img src= "/img/loading.gif" data-lazy-src="Install-Collectd-on-Ubuntu-568x450.png" alt="在Ubuntu上安装Collectd"></a></p><p>在Debian / Ubuntu上安装Collectd</p><h5 id="在RHEL-CentOS-6-x-5-x上"><a href="#在RHEL-CentOS-6-x-5-x上" class="headerlink" title="在RHEL / CentOS 6.x / 5.x上"></a>在RHEL / CentOS 6.x / 5.x上</h5><p>像<strong>CentOS的/ Fedora的</strong>旧的基于<strong>RedHat</strong>系统<strong>中</strong> ，你首先需要<a href="https://www.howtoing.com/how-to-enable-epel-repository-for-rhel-centos-6-5/">启用EPEL软件库</a>系统下，那么你就可以能够从EPEL软件库安装<strong>collectd</strong>包。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"># yum install collectd</span><br></pre></td></tr></table></figure><h5 id="在RHEL-CentOS-7-x上"><a href="#在RHEL-CentOS-7-x上" class="headerlink" title="在RHEL / CentOS 7.x上"></a>在RHEL / CentOS 7.x上</h5><p>在最新版本的RHEL / CentOS 7.x上，您可以从默认yum repo安装和启用epel存储库，如下所示。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># yum install epel-release</span><br><span class="line"># yum install collectd</span><br></pre></td></tr></table></figure><p><a href="https://www.howtoing.com/wp-content/uploads/2015/04/Install-Collectd-on-CentOS-620x344.png"><img src= "/img/loading.gif" data-lazy-src="Install-Collectd-on-CentOS-620x344.png" alt="在CentOS上安装Collectd"></a></p><p>在CentOS / RHEL / Fedora上安装Collectd</p><p><strong>注意：</strong>对于Fedora用户，无需启用任何第三方的仓库，简单yum来获得默认的yum仓库的collectd包。</p><p>**2.**一旦软件包安装在系统上，以启动该服务运行以下命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># service collectd start[On Debian based Systems]</span><br><span class="line"># service collectd start                        [On RHEL&#x2F;CentOS 6.x&#x2F;5.x Systems]</span><br><span class="line"># systemctl start collectd.service              [On RHEL&#x2F;CentOS 7.x Systems]</span><br></pre></td></tr></table></figure><h3 id="第2步：安装Collectd-Web和依赖关系"><a href="#第2步：安装Collectd-Web和依赖关系" class="headerlink" title="第2步：安装Collectd-Web和依赖关系"></a>第2步：安装Collectd-Web和依赖关系</h3><p><strong>3.<strong>开始导入</strong>Collectd的Web</strong> Git仓库之前，首先需要保证<strong>的Git</strong>软件包及以下所需的相关计算机上安装：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">----------------- On Debian &#x2F; Ubuntu systems -----------------</span><br><span class="line"># apt-get install git</span><br><span class="line"># apt-get install librrds-perl libjson-perl libhtml-parser-perl</span><br></pre></td></tr></table></figure><p><a href="https://www.howtoing.com/wp-content/uploads/2015/04/Install-Git-on-Ubuntu-620x242.png"><img src= "/img/loading.gif" data-lazy-src="Install-Git-on-Ubuntu-620x242.png" alt="在Ubuntu上安装Git"></a></p><p>在Debian / Ubuntu上安装Git</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">----------------- On RedHat&#x2F;CentOS&#x2F;Fedora based systems -----------------</span><br><span class="line"># yum install git</span><br><span class="line"># yum install rrdtool rrdtool-devel rrdtool-perl perl-HTML-Parser perl-JSON</span><br></pre></td></tr></table></figure><p><a href="https://www.howtoing.com/wp-content/uploads/2015/04/Install-Git-on-CentOS-620x344.png"><img src= "/img/loading.gif" data-lazy-src="Install-Git-on-CentOS-620x344.png" alt="在CentOS上安装Git"></a></p><p>安装Git和依赖关系</p><h3 id="第3步：导入Collectd-Web-Git存储库并修改独立的Python服务器"><a href="#第3步：导入Collectd-Web-Git存储库并修改独立的Python服务器" class="headerlink" title="第3步：导入Collectd-Web Git存储库并修改独立的Python服务器"></a>第3步：导入Collectd-Web Git存储库并修改独立的Python服务器</h3><p><strong>4.<strong>在下一步选择和更改目录从Linux树层次结构要导入Git项目（可以使用系统路径<code>/usr/local/</code>路径），然后运行下面的命令来克隆</strong>Collectd的Web</strong> git仓库：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># cd &#x2F;usr&#x2F;local&#x2F;</span><br><span class="line"># git clone https:&#x2F;&#x2F;github.com&#x2F;httpdss&#x2F;collectd-web.git</span><br></pre></td></tr></table></figure><p><a href="https://www.howtoing.com/wp-content/uploads/2015/04/Clone-Collectd-Web-620x344.png"><img src= "/img/loading.gif" data-lazy-src="Clone-Collectd-Web-620x344.png" alt="Git Clone Collectd-Web"></a></p><p>Git Clone Collectd-Web</p><p><strong>5.<strong>一旦Git仓库导入到系统中，继续前进，进入</strong>collectd-web</strong>目录<strong>，</strong>并以确定的Python服务器脚本（列出其内容<code>runserver.py</code> ），这将在下一步进行修改。 此外，添加执行权限下列CGI脚本： <code>graphdefs.cgi</code> 。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># cd collectd-web&#x2F;</span><br><span class="line"># ls</span><br><span class="line"># chmod +x cgi-bin&#x2F;graphdefs.cgi</span><br></pre></td></tr></table></figure><p><a href="https://www.howtoing.com/wp-content/uploads/2015/04/Set-Execute-Permission-620x344.png"><img src= "/img/loading.gif" data-lazy-src="Set-Execute-Permission-620x344.png" alt="设置执行权限"></a></p><p>设置执行权限</p><p><strong>6.</strong> <strong>Collectd的Web</strong>独立的Python服务器脚本默认配置来运行和约束只在<strong>环回地址（127.0.0.1）。</strong></p><p>为了从远程浏览器访问<strong>Collectd的Web</strong>界面，您需要编辑<code>runserver.py</code>脚本并更改<strong>127.0.1.1 IP</strong>地址为<strong>0.0.0.0，</strong>以绑定所有网络接口IP地址。</p><p>如果要仅在特定接口上绑定，则使用该接口IP地址（不建议使用此选项，以防您的网络接口地址由DHCP服务器动态分配）。 使用下面的截图作为最后如何摘录<code>runserver.py</code>脚本应该是这样的：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"># nano runserver.py</span><br></pre></td></tr></table></figure><p><a href="https://www.howtoing.com/wp-content/uploads/2015/04/Configure-Collect-web-620x361.png"><img src= "/img/loading.gif" data-lazy-src="Configure-Collect-web-620x361.png" alt="配置Collect-Web"></a></p><p>配置Collect-web</p><p>如果你想使用其他网络端口超过<strong>8888，</strong>修改端口变量的值。</p><h3 id="第4步：运行Python-CGI独立服务器并浏览Collectd-web界面"><a href="#第4步：运行Python-CGI独立服务器并浏览Collectd-web界面" class="headerlink" title="第4步：运行Python CGI独立服务器并浏览Collectd-web界面"></a>第4步：运行Python CGI独立服务器并浏览Collectd-web界面</h3><p>**7.**当你修改了独立的Python脚本，服务器IP地址绑定，继续前进并发出以下命令来启动服务器在后台：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"># .&#x2F;runserver.py &amp;</span><br></pre></td></tr></table></figure><p>可选，作为一种替代方法，您可以调用Python解释器启动服务器：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"># python runserver.py &amp;</span><br></pre></td></tr></table></figure><p><a href="https://www.howtoing.com/wp-content/uploads/2015/04/Start-Collect-Web-620x344.png"><img src= "/img/loading.gif" data-lazy-src="Start-Collect-Web-620x344.png" alt="启动Collect-Web服务器"></a></p><p>启动Collect-Web服务器</p>]]></content>
      
      
      
    </entry>
    
    
    
    <entry>
      <title>collectd+Graphite+Grafana搭建网络质量监控系统</title>
      <link href="operation/collectd-graphite-grafana/"/>
      <url>operation/collectd-graphite-grafana/</url>
      
        <content type="html"><![CDATA[<p>这是一篇发表已超过三年的旧文，文中的信息可能已经有所发展或是发生改变。</p><p>前段时间<a href="https://wzyboy.im/post/1070.html">入手一台 Gen8 服务器</a>，主要用来做网络存储。光做网络存储显然太浪费了，感谢 ESXi，一机多用很方便。本文介绍如何在家庭服务器上搭建简单好用的网络质量监控系统。</p><h2 id="一、选材"><a href="#一、选材" class="headerlink" title="一、选材"></a>一、选材</h2><p>说到网络质量监控，大部分人会想到著名的 <a href="http://oss.oetiker.ch/smokeping/">SmokePing</a>。SmokePing 的确是经典工具，但未免老旧，配置也略复杂。本文使用 <a href="https://collectd.org/">collectd</a> 作为收集工具，<a href="http://graphite.readthedocs.org/">Graphite</a> 作为存储工具，<a href="http://docs.grafana.org/">Grafana</a> 作为展示工具。这些工具符合「专做一件事情并把这件事情做好」的 Unix 哲学，配置灵活、功能强大。</p><p>整体结构是这样的：</p><p><img src= "/img/loading.gif" data-lazy-src="asciiflow-collectd-graphite-grafana-2.png" alt="asciiflow-collectd-graphite-grafana-2"></p><h2 id="二、收集：collectd"><a href="#二、收集：collectd" class="headerlink" title="二、收集：collectd"></a>二、收集：collectd</h2><p>正如其名字所暗示的那样，collectd 是一个收集系统各项指标的进程。它自带很多插件，也可以通过自定义插件和数据类型的方式增加更多的收集项。网络质量监控主要用到其中的 <a href="https://collectd.org/wiki/index.php/Plugin:Ping">ping 插件</a>，该插件依赖 <a href="http://noping.cc/">Liboping</a> 这个库。这两个项目在主流 GNU/Linux 发行版中都有打包。</p><p>使用你最喜爱的包管理器安装 collectd 和 liboping 之后，使用你最喜爱的编辑器打开 <code>/etc/collectd.conf</code> 文件。这是一个带有详尽注释的超长配置文件，要让 ping 插件工作，以下是一份示例配置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">Hostname &quot;your-hostname&quot;</span><br><span class="line">FQDNLookup false</span><br><span class="line"></span><br><span class="line">LoadPlugin ping</span><br><span class="line">LoadPlugin write_graphite</span><br><span class="line"></span><br><span class="line">&lt;Plugin ping&gt;</span><br><span class="line">  Host &quot;8.8.8.8&quot;</span><br><span class="line">  Host &quot;8.8.4.4&quot;</span><br><span class="line">  Interval 1.0</span><br><span class="line">  Timeout 0.9</span><br><span class="line">&lt;&#x2F;Plugin&gt;</span><br><span class="line"></span><br><span class="line">&lt;Plugin write_graphite&gt;</span><br><span class="line">  &lt;Node &quot;localhost&quot;&gt;</span><br><span class="line">    Host &quot;localhost&quot;</span><br><span class="line">    Port &quot;2003&quot;</span><br><span class="line">    Protocol &quot;tcp&quot;</span><br><span class="line">    LogSendErrors true</span><br><span class="line">  &lt;&#x2F;Node&gt;</span><br><span class="line">&lt;&#x2F;Plugin&gt;</span><br></pre></td></tr></table></figure><p>意义很明确，声明自己的主机名（用于上报数据），加载 ping 和 write_graphite 插件，然后配置这两个插件。</p><p>ping 插件的配置项中，Host 用于添加需要被监控的目标，一行一个，<code>Interval</code> 和 <code>Timeout</code> 则分别指定多久 ping 一次，以及多久没收到回包认为是超时。如有特殊需求，还可以指定 <code>SourceAddress</code>, <code>Device</code> 等参数指定从哪个网络设备发出 ICMP 包。注意，这里 <code>Interval</code> 不是指多久上报一次，而是指多久 ping 一次，上报的话还是按全局的来（默认 10 秒），上报时的数据是这段时间 RTT 的算术平均数。</p><p>write_graphite 插件的配置项中，填写 carbon-cache.py 监听的地址和端口。本例中跑 collectd 的机器同时也跑了 carbon-cache.py，因此填 localhost 即可。如果它们不在同一台机器上（比如 collectd 跑在路由器上，carbon-cache.py 跑在配置更高的设备上），则需要填写相应的地址。</p><p>collectd 发出去的数据是很简单的 TCP 消息，如：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">foo.bar.baz 123 1458372405</span><br></pre></td></tr></table></figure><p>以空格分隔，第一段是指标名字，第二段是数值，第三段是时间戳。</p><p>改好配置之后保存。因为现在 carbon-cache.py 还没有运行，因此还不能启动 collectd。</p><h2 id="三、接收、存储和查询：carbon-cache-py-和-graphite-api"><a href="#三、接收、存储和查询：carbon-cache-py-和-graphite-api" class="headerlink" title="三、接收、存储和查询：carbon-cache.py 和 graphite-api"></a>三、接收、存储和查询：carbon-cache.py 和 graphite-api</h2><p>Graphite 是一个较大项目，它的主要组件有：</p><ul><li><a href="https://github.com/graphite-project/carbon">Carbon</a>。包括 carbon-cache.py, carbon-relay.py 等，用于接收数据点；</li><li><a href="https://github.com/graphite-project/whisper">Whisper</a>。数据点存储格式，Carbon 用它把数据点写入磁盘；</li><li>Graphite Web。基于 Django 的网页应用，既提供查询数据点的 API，也提供一个展示用的网页。</li></ul><p>由于 Graphite Web 较为臃肿而功能比较弱，因此这里不使用它，而是使用 <a href="https://github.com/brutasse/graphite-api">Graphite-API</a> 这个第三方项目提供查询 API，用漂亮的 Grafana 提供展示页面。</p><p>Carbon 可以直接从 PyPI 安装，注意它只支持 Legacy Python。它是纯 Python 的，没有其他依赖，使用 <code>pip2 install carbon</code> 即可轻松安装。</p><p>Carbon 使用 Whisper 存储数据点，这一格式的文件大小是预分配的，并且是固定的。旧的数据可以设置自动降低精度，非常旧的数据可以设置丢弃。在 <code>storage-schemas.conf</code> 中可以这么设置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">[ping]</span><br><span class="line">pattern &#x3D; \.ping\.</span><br><span class="line">retentions &#x3D; 10s:1d,1m:30d,5m:180d,30m:1y</span><br><span class="line"></span><br><span class="line">[default]</span><br><span class="line">pattern &#x3D; .*</span><br><span class="line">retentions &#x3D; 1m:1d,5m:30d,30m:180d,1h:1y</span><br></pre></td></tr></table></figure><p>其中 pattern 匹配指标的名字，retentions 指定这个指标应该保留多久。以 <code>[default]</code> 为例，这个指标的数据，1 分钟精度的会保留 1 天，之后自动降为 5 分钟精度，保留 30 天，之后自动降为 30 分钟精度，保留 180 天，之后自动降为 1 小时精度，保留 1 年。而对于 <code>[ping]</code> 一节的数据，我希望能更精确一些，因此 1 天内的数据是 10 秒精度的。这样的设置可以使不同的指标按需自动降低精度以节省存储空间，既能查到近期的高精度数据，也能反观远期的大致趋势。</p><p>注意这些政策仅对新创建的 <code>.wsp</code> 文件有效，已有的文件的存储策略需要通过 whisper-resize.py 进行更改。<br>Graphite-API 因为带有非 Python 的图形库依赖，编译安装时较为麻烦。Ubuntu / Debian 用户可以用官方提供的 <a href="https://github.com/brutasse/graphite-api/releases">.deb</a> 安装。Arch Linux 用户可以使用我打包的 <a href="https://aur.archlinux.org/packages/graphite-api/">aur/graphite-api</a> 安装。</p><p>安装之后打开 <code>graphite-api.yaml</code> 文件。根据安装方式的不同，Carbon 和 Graphite-API 的存储路径、配置文件路径会有一些差别，请按照自己的情况将 whisper – directories 一节的路径填写正确。</p><p>另外推荐配置 carbonlink，查询那些在 <code>carbon-cache.py</code> 内存中还未写入磁盘的数据。最终我使用的 <code>graphite-api.yaml</code> 内容如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">finders:</span><br><span class="line">  - graphite_api.finders.whisper.WhisperFinder</span><br><span class="line">whisper:</span><br><span class="line">  directories:</span><br><span class="line">    - &#x2F;var&#x2F;lib&#x2F;carbon&#x2F;whisper</span><br><span class="line">carbon:</span><br><span class="line">  hosts:</span><br><span class="line">    - 127.0.0.1:7002</span><br><span class="line">  timeout: 1</span><br><span class="line">  retry_delay: 15</span><br><span class="line">  carbon_prefix: carbon</span><br><span class="line">  replication_factor: 1</span><br></pre></td></tr></table></figure><p>配置完成后，可以启动 carbon-cache.py 和 graphite-api。上节配置的 collectd 也可以启动了。</p><h2 id="四、展示：grafana-server"><a href="#四、展示：grafana-server" class="headerlink" title="四、展示：grafana-server"></a>四、展示：grafana-server</h2><p>Grafana 是一个功能强大的图表绘制服务器，支持 Graphite, InfluxDB, OpenTSDB 等多种后端，支持多种图表绘制，几乎无外部依赖。</p><p>Grafana 由 Go 和 Node.js 写成，编译结果是一个单文件 Go 程序和一堆 HTML + CSS + JavaScript。官方提供了 <a href="http://docs.grafana.org/installation/debian/">.deb</a> 和 <a href="http://docs.grafana.org/installation/rpm/">.rpm</a> 可供安装。我在 Arch Linux 上安装的时候，本来直接用的 aur/grafana，后来发现 go get 和 npm install 的过程简直蛋疼，于是将官方提供的 <a href="http://grafana.org/download/">.tar.gz</a> 二进制包做了一份 <a href="https://aur.archlinux.org/packages/grafana-bin/">aur/grafana-bin</a>，直接装这个就省力多了。</p><p>安装之后启动服务，在浏览器中打开 :3000 端口，即可用 admin / admin 登录。在 <code>grafana.ini</code> 中也可以开启匿名登录。</p><p>登录后需要先添加数据源（data source），将 graphite-api 的地址和端口（默认是 8888）填写进去即可。</p><p>然后便可以开始画图了，通过简单的网页操作即可添加各种不同类型的图表，也可以方便地选用 Graphite 内置的各种函数。Grafana 的具体操作可以从<a href="http://docs.grafana.org/guides/gettingstarted/">官方文档</a>了解到，这里不再赘述。</p><p>以下是我用 Grafana 绘制的网络质量监控的页面，其中用到 <a href="http://docs.grafana.org/reference/templating/">Templating</a>、<a href="http://docs.grafana.org/reference/singlestat/">Singlestat Panel</a> 等功能：</p><p><img src= "/img/loading.gif" data-lazy-src="grafana-dashboard-network-fullscreen-20160319-2-blurred.png"></p><p>请原谅那一段 100% 丢包率的部分，是我的一台 VPS 所在的机房出了问题……</p><h2 id="五、监控更多的指标"><a href="#五、监控更多的指标" class="headerlink" title="五、监控更多的指标"></a>五、监控更多的指标</h2><p>collectd 还可以做<a href="https://collectd.org/wiki/index.php/Table_of_Plugins">很多事情</a>，只用它的 ping 插件太大材小用了。玩熟了 ping 插件之后，我又用它监控了局域网内各机器（自己的笔记本、Gen8 上运行的其他虚拟机等）的 CPU、内存、磁盘、网络等其他指标。collectd 的客户端也是移植性很强，我甚至在 Raspberry Pi 上也部署了一下。Windows 机器的话，则可以安装 <a href="https://collectd.org/wiki/index.php/SSC_Serv">SSC Serv</a>，这是一个协议兼容的 collectd agent，免费版本有五分钟上报一次的限制，基本够用了。</p><p>by wzyboy on 2016-03-21</p><hr><h1 id="graphite"><a href="#graphite" class="headerlink" title="graphite"></a>graphite</h1>]]></content>
      
      
      
        <tags>
            
            <tag> graphite </tag>
            
            <tag> collectd </tag>
            
            <tag> grpfana </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中接口的多继承</title>
      <link href="java/javase/java-dup-inheritance/"/>
      <url>java/javase/java-dup-inheritance/</url>
      
        <content type="html"><![CDATA[<h1 id="Java中接口的多继承"><a href="#Java中接口的多继承" class="headerlink" title="Java中接口的多继承"></a>Java中接口的多继承</h1><p><a href="https://www.jianshu.com/u/3c084cab313c"><img src= "/img/loading.gif" data-lazy-src="6d33af4a-cc0f-4e11-ac41-d6135f7e6d8e.png" alt="img"></a></p><p>我们知道Java的类只能继承一个类，但可以实现多个接口。但是你知道么？Java中的接口却可以继承多个接口。本文就来说一说Java中接口的多继承。</p><p>进入主题之前，先扩展一下。Java为什么只支持单继承呢？</p><p>我们不妨假设Java支持多继承，举个例子，在这里有个A类，我们又编写了两个类B类和C类，并且B类和C类分别继承了A类，并且对A类的同一个方法进行了覆盖。如果此时我们再次编写了一个D类，并且D类以多继承的方式同时集成了B类和C类，那么D类也会继承B类和C类从A类中重载的方法，如下图所示。那么问题来了，D类也开始犯迷糊了，我到底应该哪个继承哪个类中的方法呢，因为类是结构性的，这样就会造成结构上的混乱。这就是多继承的菱形继承问题。</p><p><img src= "/img/loading.gif" data-lazy-src="5679451-43aab94c4bdff320.png" alt="img"></p><p>同时我们知道C++是支持多继承的，因为它解决了这个问题（我对C++不太熟，查了下资料，好像是通过虚基类实现的吧）。但是Java本着简单的原则，舍弃了多继承。</p><p>好，进入正题。我们还是举个实例来演示一下接口的多继承。</p><p>燕子是鸟，鸟会飞，也会唱歌。我们来模仿一下：</p><p><strong>一、会飞的接口</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> multiex;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Flyable</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>二、会唱歌的接口</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> multiex;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Singable</span>  </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">sing</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>三、鸟的接口</strong><br>鸟的接口继承上面两个接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> multiex;</span><br><span class="line"><span class="comment">//虽然这个接口没有定义方法，但是会继承下来两个方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Bird</span> <span class="keyword">extends</span> <span class="title">Flyable</span>,<span class="title">Singable</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>四、燕子类，实现鸟接口</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> multiex;</span><br><span class="line"></span><br><span class="line"><span class="comment">//燕子类</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Swallow</span> <span class="keyword">implements</span> <span class="title">Bird</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;燕子会飞&quot;</span>);</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">sing</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;燕子会唱歌&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>五、测试类</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> multiex;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Swallow swallow = <span class="keyword">new</span> Swallow();</span><br><span class="line">        swallow.fly();</span><br><span class="line">        swallow.sing();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><p><img src= "/img/loading.gif" data-lazy-src="5679451-5200410893ef3a5e.png" alt="img"></p><p>上面演示了接口的多继承，那么这里存在一个问题。如果多个接口中有重名的方法怎么办？比如如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> multiex;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">m</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//注意：方法返回值不一样</span></span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">B</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">m</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span> <span class="keyword">implements</span> <span class="title">A</span>, <span class="title">B</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;void m()&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">m</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;int m()&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        C c1 = <span class="keyword">new</span> C();</span><br><span class="line">        c1.m();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这时，编译将无法通过。如下图所示：</p><p><img src= "/img/loading.gif" data-lazy-src="5679451-f1a242d24a2186d4.png" alt="img"></p><p>因为在Java中，<br><strong>方法名+参数（不含返回值类型）唯一确定一个方法。</strong><br><strong>方法名+参数（不含返回值类型）唯一确定一个方法。</strong><br><strong>方法名+参数（不含返回值类型）唯一确定一个方法。</strong></p><p>所以当返回值不同时，Java认为这还是同一个方法，会与其中一个接口的返回类型冲突。导致编译错误。</p><p>同理，当返回值相同时，那这完全就是同一个方法了，实现类实现一次这个方法就好了。如下图：</p><p><img src= "/img/loading.gif" data-lazy-src="5679451-17a504ccd13fbb6f.png" alt="img"></p><p>怎么样？同学你懂了没？</p>]]></content>
      
      
      
        <tags>
            
            <tag> java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>漫话：如何给女朋友解释鸿蒙OS是怎样实现跨平台的？</title>
      <link href="comic/harmony-introduce/"/>
      <url>comic/harmony-introduce/</url>
      
        <content type="html"><![CDATA[<p><img src= "/img/loading.gif" data-lazy-src="p-1616588503900" alt="640?wx_fmt=jpeg"> </p><p>周末在家休息，女朋友在刷朋友圈，突然她问我：</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588520743" alt="640?wx_fmt=jpeg"> </p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587756118" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587756170" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587756118" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587856162" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587856191" alt="640?wx_fmt=jpeg"></p><p>鸿蒙OS回顾</p><blockquote><p>2019年8月9日华为开发者大会上，华为消费者业务CEO余承东正式宣布发布自有操作系统鸿蒙，内核为Linux内核、鸿蒙微内核和LiteOS。未来将摆脱Linux内核和LiteOS，只有鸿蒙微内核。</p></blockquote><p>鸿蒙（英语：Harmony OS，开发代号Ark）是华为自2012年开发的一款可能兼容Android app的跨平台操作系统。</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587898976" alt="640?wx_fmt=jpeg"></p><p> 图：鸿蒙OS的四大技术特性</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587910481" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587910390" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587910434" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616587910391" alt="640?wx_fmt=jpeg"></p><p> <img src= "/img/loading.gif" data-lazy-src="p-1616587920932" alt="640?wx_fmt=jpeg"> </p><p> 什么是跨平台 </p><p> 在以前，<code>平台 ≈ 操作系统</code>。所以，传统意义上的跨平台即不依赖于操作系统，也不依赖硬件环境。一个操作系统下开发的应用，放到另一个操作系统下依然可以运行。 </p><p> 但是随着科技的发展，<code>平台 ≈ 操作系统</code>已经不成立了，就像华为推出的鸿蒙OS，他可以支持到多种多样的设备，如手机、手表、电脑、汽车、智能家居设备等 </p><p><img src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_jpg/C1uDMDqjn1ibEXMVp5gicrRHq5ibFJwLxTLr9SaQJmpdghdwkAnQSBPFGpq9o5hV8gTpBIqI11VP5AViciaZV9wBunw/640?wx_fmt=jpeg" alt="640?wx_fmt=jpeg"></p><p>所以，今天我们谈的跨平台，指的是跨设备。即<code>平台 ≈ 设备</code></p><p><img src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_jpg/C1uDMDqjn1ibEXMVp5gicrRHq5ibFJwLxTLOknbP1PGwcH1KXa7ngPKSFicNOFkUPeP6otOUMvakk3owvRzlES0opw/640?wx_fmt=jpeg" alt="640?wx_fmt=jpeg"></p><p>所以，华为希望鸿蒙OS可以运行在各种各样的设备上，所以，鸿蒙OS必然需要具备跨平台的能力。</p><p><strong>而且，鸿蒙想要做的不仅仅是操作系统可以跨平台，更重要的是要让用户和开发者真正的感受到跨平台。</strong></p><p>所以，跨平台操作系统鸿蒙的目的是：使开发者能够聚焦自身业务逻辑，像开发同一终端一样开发跨终端分布式应用，也使最终消费者享受到强大的跨终端业务协同能力为各使用场景带来的无缝体验。</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588005956" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588005952" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588005954" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588005953" alt="640?wx_fmt=jpeg"></p><p> Java实现跨平台 </p><p> 先来说说Java是如何实现跨平台的。 </p><p>Java对于跨平台的支持，就像对安全性和网络移动性的支持一样，是分布在整个Java体系结构中的。其中扮演者重要的角色的有Java语言规范、Class文件、Java虚拟机（JVM）等。</p><p>首先，在Java语言规范中，规定了Java语言中基本数据类型的取值范围和行为。其次，所有Java文件要编译成统一的Class文件。最后，通过Java虚拟机将Class文件转成对应平台的二进制文件。</p><p>Java的平台无关性是建立在Java虚拟机的平台有关性基础之上的，是因为Java虚拟机屏蔽了底层操作系统和硬件的差异。</p><p>想要运行一段Java代码，要经过多个步骤，将Java源代码转换成机器可以执行的机器代码，这个过程主要由虚拟机来完成。</p><p>在著名的HotSpot虚拟机中，主要有解释执行和即时编译两种形式：</p><ul><li>解释执行<ul><li>逐条将字节码翻译成机器码并执行</li></ul></li><li>即时编译（Just-in-time ，JIT）<ul><li>将一个方法中包含的所有字节码编译成机器码后再执行。</li></ul></li></ul><p> HotSpot 默认采用混合模式，综合了解释执行和即时编译两者的优点。它会先解释执行字节码，而后将其中反复执行的热点代码（热点检测），以方法为单位进行即时编译。 </p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588196299" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588196338" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588196343" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588208470" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588208502" alt="640?wx_fmt=jpeg"></p><p>Android实现跨平台<br>Android其实基于Java语言的，所以同理，想要运行一段Android代码，也要经过多个步骤，将Android源代码转换成机器可以执行的机器代码。</p><p>但是这个转换过程在Android的不同版本中实现不尽相同：</p><p>Android 1.0（2008 年）：采用一个名为 Dalvik 的虚拟机，并且集成了一个解释器。当 App 运行时，就会调用这个解释器，对代码进行逐句解释，速度很慢。</p><p>Android 2.2（2010 年）：引入 JIT（Just In Time）即时编译机制，当 App 运行时，会将用户经常使用的功能编译为机器能直接执行的 010101 机器码，不用一句一句地去翻译。当出现不常用的功能时，再调用解释器来翻译；这样速度加快，但每次启动 App 都要重新编译一次，不能一劳永逸。</p><p> <img src= "/img/loading.gif" data-lazy-src="p-1616588224460" alt="640?wx_fmt=jpeg"> </p><p>Android 5.0（2014 年 10 月）：将虚拟机 Dalvik 换成 ART（Android Run Time），将 JIT 的编译器替换成 AOT（Ahead of Time）。</p><p>如此，App 在下载后安装到手机上时同时把能编译的代码先编译成机器听得懂的 101010；剩下不太好翻译的代码，就在用户使用时再叫醒解释器来翻译。如此，不用每次打开 App 都需要编译，但安装 App 的时间有点长，而且占用手机空间。</p><p> <img src= "/img/loading.gif" data-lazy-src="p-1616588242328" alt="640?wx_fmt=jpeg"> </p><p>Android 7.0（2016 年）：采用混合编译机制，安装时先不编译中间代码，而是在用户空闲时将能够编译成机器码的那部分代码，通过 AOT 编译器先静态编译了。如果 AOT 还没来得及编译或者不能编译，再调用 JIT+ 解释器。这种机制，相当于用时间换空间，既缩短了用户安装 APP 的等待时间，又将虚拟机里编译器和解释器能做的优化提升到最大效率了。<br> <img src= "/img/loading.gif" data-lazy-src="p-1616588252014" alt="640?wx_fmt=jpeg"> </p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588265072" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588265091" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588265096" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588275237" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588275258" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588275267" alt="640?wx_fmt=jpeg"></p><p>Android编译的问题<br>可以看到，从2008年的Android 1.0开始，Android在编译优化上面在一直下功夫。</p><p>当前的 Android 采用的是解释执行 + JIT + AOT 的综合模式，在 空间占用+安装速度+运行速度 上已经达到了一个很好的平衡。</p><p>但是Android的编译问题一直被诟病。尽管在后续的Android 8.0 上改进了解释器，解释模式执行效率大幅提升；Android 10.0 上提供了预先放置热点代码的方式，应用在安装的时候就能知道常用代码会被提前编译。</p><p>但是，目前来看，无论如何，Android都没能摆脱这样一个前提：即应用在被打包成 APK 的时候，采用的还是 Java 代码。换句话说，在 APK 变成用户可应用的过程中，还经历了一个在 Android 系统内部的编译过程，这是一个绕不过的坎。</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588296938" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588296943" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588296951" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588307315" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588307321" alt="640?wx_fmt=jpeg"></p><p>鸿蒙实现跨平台</p><p> 那么，鸿蒙OS的代码编译是怎么样的呢？他又是如何解决跨平台的问题的呢？ </p><p> <img src= "/img/loading.gif" data-lazy-src="p-1616588315526" alt="640?wx_fmt=jpeg"> </p><p>从上图中可以看到，在鸿蒙OS架构中，<strong>方舟编译器</strong>和<strong>多终端开发IDE</strong>扮演着重要的位置。</p><p>跨平台有一个最大的挑战，那就是各个平台的适配问题，尤其是目前各种设备类型越来越多，如何将同一个应用，在手机、手表、汽车、电视上面都可以适配的展示呢？这就是多终端开发IDE所做的事情。</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588331837" alt="640?wx_fmt=jpeg"></p><p>使用华为提供的多终端IDE，多语言统一编译，分布式架构Kit提供屏幕布局控件以及交互的自动适配，支持控件拖拽，面向预览的可视化编程，从而使开发者可以基于同一工程高效构建多端自动运行App，实现真正的一次开发，多端部署，在跨设备之间实现共享生态。</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588331876" alt="640?wx_fmt=jpeg"></p><p>上图就是华为提供的IDE，在里面可以通过图形化界面拖拽控件，并且IDE可以帮助自动适配各种终端设备。</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588337851" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588337852" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588355236" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588355236" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588355237" alt="640?wx_fmt=jpeg"></p><p>有了IDE，开发可以方便的开发一套代码，这样可以自动适配到各种设备中，但是各种设备所执行的机器指令是不一样的，如何把这一套代码分别编译成各个设备需要的机器指令呢？</p><p>Android设备是由不同设备上内置的虚拟机进行编译的，所以编译之前就知道这个设备具体是什么了，那么，鸿蒙OS是怎么做的呢？这就是方舟编译器所干的事情了。</p><p>华为方舟编译器是首个取代Android虚拟机模式的静态编译器，可供开发者在开发环境中一次性将高级语言编译为机器码。此外，方舟编译器未来将支持多语言统一编译，可大幅提高开发效率。</p><p> <img src= "/img/loading.gif" data-lazy-src="p-1616588384070" alt="640?wx_fmt=jpeg"> </p><p>Android之所以”慢”，是因为他的编译过程是在终端进行的，也就是说需要在用户的手机上，通过虚拟机进行编译成可执行的机器代码。</p><p>而鸿蒙OS使用的方舟编译器，可以将高级语言（Java）直接变成机器码，从而绕过了虚拟机。并且这个编译过程并不是在用户的手机上完成的，而是在应用开发阶段就完成了。<br> <img src= "/img/loading.gif" data-lazy-src="p-1616588393308" alt="640?wx_fmt=jpeg"> </p><p>通过方舟编译器，开发者的应用在下载之前就已经转化成为机器可以识别的代码，因而可以在手机上快速安装、启动和运行，而无需在经过 VM 的编译——某种程度上，方舟编译器是将编译过程提前到应用开发阶段，从而大幅度减少了智能手机和操作系统的运行负担。</p><p>华为官方介绍，方舟编译器是首家完全替代语言虚拟机的静态编译器，完全不需要解释器。兼顾Java开发效率和C语言运行效率的编译器。</p><p>除了代码编译，方舟编译器也提供了更高效的内存机制，它与 Android 内存回收的不同之处在于：</p><p>Android 在内存回收上采用集中回收机制，发声全局回收时更需要暂停应用，这也是随机卡顿的根因之一。而方舟编译器采用了引用计数法来进行内存的实时回收，并且配合使用了专门的消除环算法（消除对象互相引用带来的无法回收问题），来避免 GC 集中式回收带来的系统卡顿。相比 GC，方舟的内存回收是实时的而非集中式的，且不需要暂停应用进程，这样便大大消除了卡顿。</p><p> <img src= "/img/loading.gif" data-lazy-src="p-1616588405581" alt="640?wx_fmt=jpeg"> </p><p>另外，就像JVM其实也是支持多种语言一样，华为表示，方舟编译器未来也会支持更过的开发语言。换句话说，其他语言的开发者，日后也能开发基于鸿蒙OS的应用。</p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588419053" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588419060" alt="640?wx_fmt=jpeg"></p><p><img src= "/img/loading.gif" data-lazy-src="p-1616588419080" alt="640?wx_fmt=jpeg"></p><p> <img src= "/img/loading.gif" data-lazy-src="p-1616588433001" alt="640?wx_fmt=jpeg"> </p><p>参考资料： </p><p><a href="https://www.jishuwen.com/d/2NN3">https://www.jishuwen.com/d/2NN3</a> </p><p><a href="https://www.zhihu.com/question/339567108">https://www.zhihu.com/question/339567108</a> </p><p><a href="https://www.cnbeta.com/articles/tech/876171.htm">https://www.cnbeta.com/articles/tech/876171.htm</a> <a href="https://www.cnbeta.com/articles/tech/876919.htm">https://www.cnbeta.com/articles/tech/876919.htm</a> <a href="https://juejin.im/post/5cb07000f265da037d4f9be6">https://juejin.im/post/5cb07000f265da037d4f9be6</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> system </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>玩转Obsidian-基础设置篇</title>
      <link href="comic/use-obsidian/"/>
      <url>comic/use-obsidian/</url>
      
        <content type="html"><![CDATA[<p><img src= "/img/loading.gif" data-lazy-src="16046439499952.jpg" alt="img"></p><p>玩转 Obsidian | 基础设置篇</p><p><a href="https://sspai.com/u/5b3wva6y/updates"><img src= "/img/loading.gif" data-lazy-src="fb21dd16513c7d710210d767a409264b.png" alt="闲者时间_王掌柜"></a><a href="https://sspai.com/u/5b3wva6y/updates">闲者时间_王掌柜</a></p><p>2020年11月06日</p><h3 id="Matrix-精选"><a href="#Matrix-精选" class="headerlink" title="Matrix 精选"></a><strong>Matrix 精选</strong></h3><p><a href="https://sspai.com/matrix">Matrix</a> 是少数派的写作社区，我们主张分享真实的产品体验，有实用价值的经验与思考。我们会不定期挑选 Matrix 最优质的文章，展示来自用户的最真实的体验和观点。</p><p>文章代表作者个人观点，少数派仅对标题和排版略作修改。</p><hr><p><a href="https://obsidian.md/">Obsidian</a> 是一款非常优秀的「现代化」笔记管理工具，因其快速的功能迭代和优秀社区活跃度，成为了近期较为热门的笔记软件之一。个人经过一段时间的使用和体验，认为 Obsidian 已经具备了成为「主力笔记管理软件」的能力，并陆续将自己的笔记迁移到 Obsidian 上进行管理。</p><p>Obsidian 和其他常见的「笔记软件」有什么不同，它具备哪些优势，以及想要用好 Obsidian 有哪些「方法论」，我在上一篇文章《<a href="https://sspai.com/post/62414">玩转 Obsidian | 打造知识循环利器</a>》中有过详细的阐述，感兴趣的同学可以先翻过去了解一下。</p><p>由于后续我打算持续更新「玩转 Obsidian」系列文章，所以迫切需要一篇「关于基础设置和使用介绍」的入门级介绍文章，于是有了本篇。</p><p>碍于篇幅，我不可能将所有的功能都罗列出来，本篇「<strong>只适用于快速上手体验</strong>」，文中介绍的是个人认为比较重要的设定和使用方法。如果想了解 Obsidian 的所有功能特点，Obsidian 官方非常贴心的提供了帮助文档《<a href="https://publish.obsidian.md/help/Index">Obsidian Help</a>》，同时为了方便大家进行「交互式」体验其功能，Obsidian 还内置了「Obsidian Help」仓库，并且以上两个文档都会得到官方的持续更新，大家可以选择任意方式进行阅读。</p><p>PS：本篇文章基于 Obsidian <code>v0.9.10</code> 版本。</p><h2 id="Obsidian-的基本使用"><a href="#Obsidian-的基本使用" class="headerlink" title="Obsidian 的基本使用"></a>Obsidian 的基本使用</h2><p>大家可以去 <a href="https://obsidian.md/">Obsidian 官网</a>下载对应的客户端，由于使用了跨平台的「前端技术」，Obsidian 同时支持多个「桌面平台」的使用，当你安装好 Obsidian 后，我们就可以简单的设置并使用它写笔记。</p><h3 id="新建仓库"><a href="#新建仓库" class="headerlink" title="新建仓库"></a>新建仓库</h3><p>Obsidian 支持「仓库」概念，我们可以将自己的「个人笔记」和「工作笔记」创建不同的仓库，这样他们之间的内容互不影响，当然一切都是自由的，你可以任意创建属于自己的「仓库」。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513203.png" alt="新建仓库">新建仓库</p><p>PS：如果我们设置仓库的存储目录为「云盘」的时候，Obsidian 就具备了「云同步」的能力。</p><p><img src= "/img/loading.gif" data-lazy-src="https://cdn.sspai.com/editor/u_5b3wva6y/16046439513220.png?imageView2/2/w/1120/q/90/interlace/1/ignore-error/1" alt="云端管理">云端管理</p><h3 id="Obsidian-的基本布局"><a href="#Obsidian-的基本布局" class="headerlink" title="Obsidian 的基本布局"></a>Obsidian 的基本布局</h3><p>Obsidian 的布局比较直观，如下图一些基本的操作和入口我已经标注出来，这里大家只需要做下了解：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513232.png" alt="基本布局">基本布局</p><h3 id="新建笔记"><a href="#新建笔记" class="headerlink" title="新建笔记"></a>新建笔记</h3><p>Obsidian 支持多种创建笔记方式，最简单的就是使用快捷键「CMD + N」，也可以在「资源管理面板」中点击「新建笔记」按钮。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513244.png" alt="新建笔记">新建笔记</p><h2 id="通用设置"><a href="#通用设置" class="headerlink" title="通用设置"></a>通用设置</h2><p>以下将介绍 Obsidian 的通用设置，包括主题设置、标签管理、编辑模式 VS 预览模式、命令模式、工作区管理等。</p><h3 id="主题设置"><a href="#主题设置" class="headerlink" title="主题设置"></a>主题设置</h3><p>由于 Obsidian 使用了前端技术，理论上通过 CSS 技术可以实现各种样式和布局，在 Obsidian 中设置「样式」也非常简单。</p><p>第一步，开启「自定义主题」插件：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513256.png" alt="img"></p><p>第二步，选择符合自己的主题： </p><p><img src= "/img/loading.gif" data-lazy-src="16046439513269.jpg" alt="img"></p><p>PS：作者使用的主题是「<a href="https://github.com/GuangluWu/obsidian-pisum">Pisum</a>」，如果打不开「主题样式」列表，可能遇到了不可翻越的墙，可以去 Github 搜索「Obsidian」关键字查找。</p><h3 id="附件存储设置"><a href="#附件存储设置" class="headerlink" title="附件存储设置"></a>附件存储设置</h3><p>Obsidian 支持在笔记中插入图片和音频等「附件」，为了方便管理我们的仓库，可以单独设置「附件」的存储目录，这样就不会和文件都散落在仓库中。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513281.png" alt="附件存储">附件存储</p><h3 id="标签管理"><a href="#标签管理" class="headerlink" title="标签管理"></a>标签管理</h3><p>Obsidian 支持标签管理，如果需要使用首先要开启「标签面板」。 </p><p><img src= "/img/loading.gif" data-lazy-src="16046439513295.png" alt="标签管理">标签管理</p><p>当我们在文章任意地方通过 <code>#标签名称</code> 插入标签后，就可以在「标签面板」中看到所有仓库中的标签。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513307.png" alt="标签使用">标签使用</p><h3 id="编辑模式-VS-预览模式"><a href="#编辑模式-VS-预览模式" class="headerlink" title="编辑模式 VS 预览模式"></a>编辑模式 VS 预览模式</h3><p>编辑模式，指的是在 Obsidian 中新建或打开笔记时，笔记处于「编辑」状态，此时我们可以直接输入 Markdown 语法进行编辑。</p><p>由于 Obsidian 不支持「所见即所得」的编辑模式，所以我们需要进入「预览模式」才可以看到我们笔记真实的样式，下图中可以看到他们的对比：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513320.png" alt="img"></p><p>进入「预览模式」的方式常见的几种如下：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513331.png" alt="img">通过快捷键切换 CMD + E</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513342.png" alt="img">菜单栏按钮切换</p><p>PS： 点击上图按钮时如果同时按下 CMD 键，会在右边打开新的笔记面板展示「预览模式」。</p><h3 id="命令模式"><a href="#命令模式" class="headerlink" title="命令模式"></a>命令模式</h3><p>Obsidian 也向大多数智能笔记工具一样具备「命令模式」，同样使用「CMD + P」打开命令面板，从中可以选择各种命令，如果想要查看各种命令的中文名称，可以去「仓库管理面板」切换到「中文」查看：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513353.png" alt="img"></p><h2 id="工作区管理"><a href="#工作区管理" class="headerlink" title="工作区管理"></a>工作区管理</h2><p>工作区指的是，Obsidian 会把当前打开的多个「笔记页」、「右侧扩展区域」和「Backlinks For XXX」等全部面板的「加载打开」状态等当做一个「工作区」。我们可以任意保存和加载工作区。</p><p>工作区带来的好处，当我们同时处理各种笔记的时候，具备了「一键还原现场」的能力，方便我们快速进入「心流状态」，避免我们被各种事情所打扰，迟迟不能进入状态。</p><p>使用工作区的话，首先开启「Workspaces」插件，就可以看到「工作区」操作入口了，如图： </p><p><img src= "/img/loading.gif" data-lazy-src="16046439513364.png" alt="工作区管理">工作区管理</p><p><strong>保存「工作区」：</strong>我们可以在 Obsidian 的任意界面，点击上图中「工作区操作入口」的按钮，打开「工作区管理面板」进行保存：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513374.png" alt="img"></p><p><strong>加载「工作区」：</strong>我们可以在 Obsidian 的任意界面点击上图中「工作区操作入口」的按钮，打开「工作区管理面板」进行加载操作：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513385.png" alt="img"></p><h2 id="模板输入"><a href="#模板输入" class="headerlink" title="模板输入"></a>模板输入</h2><p>在使用笔记的过程中经常会遇到需要重复输入的内容，比如会议纪要的模板，此时我们可以使用 Obsidian 的「模板输入」功能，创建好「模板」后，就可以是实现「快速输入模板」的能力，具体操作如下：</p><p>\1. 开启模板插件：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513396.png" alt="img"></p><p>\2. 设置模板目录和格式：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513406.png" alt="img"></p><p>\3. 创建模板文件：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513418.png" alt="img"></p><p>\4. 使用模板：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513430.png" alt="img"></p><p><img src= "/img/loading.gif" data-lazy-src="16046439513441.png" alt="img"></p><h2 id="超链接使用"><a href="#超链接使用" class="headerlink" title="超链接使用"></a>超链接使用</h2><p>Obsidian 支持多种「超链接语法」，这些功能也是「现代笔记管理」的必备技能。几种常见的语法如下：</p><ul><li>双向链接：<code>[[Note Name]]</code></li><li>话题引用：<code>[[Note Name #header]]</code></li><li>别名引用：<code>[[Note Name |Alias]]</code></li><li>嵌入引用：<code>！[[Note Name]]</code></li><li>块引用：<code>[[Note Name ^]]</code></li></ul><h3 id="超链接语法-双向链接"><a href="#超链接语法-双向链接" class="headerlink" title="超链接语法 - 双向链接"></a>超链接语法 - 双向链接</h3><p>「双向链接」的语法为<code>[[Note Name]]</code>，在前文中已经简单介绍过它的使用，下边是关于「双向链接」的详细介绍。</p><p>「双向链接」指的是在笔记 A 中通过输入 <code>[[笔记 B]]</code> 后，使得笔记 A 和笔记 B 建立了链接关系，如下：</p><p>在笔记A 中可以看到它和 <code>[[笔记 B]]</code> 有关系，同时在笔记 A的「预览模式」下，鼠标经过<code>[[笔记 B]]</code> 时，可以弹出笔记 B 的「缩略视图」，同时点击 <code>[[笔记 B]]</code> 后也可以打开笔记 B的编辑页面。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513451.png" alt="img"></p><p>PS：想要看到笔记 B 的「缩略视图」需要开启「Page Preview」插件。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513461.png" alt="img"></p><p>在笔记 B 中可以通过「Backlinks For 笔记B」看到都有哪些笔记和自己建立过「双向链接」。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513472.png" alt="img"></p><p>PS：「Backlinks For 笔记B」的打开方式常用的方法有两种，通过快捷键或者菜单按钮。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513485.png" alt="img"></p><p><img src= "/img/loading.gif" data-lazy-src="16046439513496.png" alt="img"></p><h3 id="超链接语法-话题引用"><a href="#超链接语法-话题引用" class="headerlink" title="超链接语法 - 话题引用"></a>超链接语法 - 话题引用</h3><p>在 Obsidian 中，由于 Obsidian 支持 Markdown 标记，我把用 <code>#</code> 标记的内容称为「话题」，如下图，「### English」和「### Chinese」就是两个「话题」： </p><p><img src= "/img/loading.gif" data-lazy-src="16046439513507.png" alt="img"></p><p>话题引用的语法是<code>[[Note Name #header]]</code>，即在使用「双向链接」的时候，我们可以在输入的「笔记名称」后边输入笔记中的「话题」，这种「双向链接」的添加方式称为「话题引用」如图：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513518.png" alt="img"></p><p>「话题引用」带来的好处是，当我们在「预览模式」下，鼠标经过「双向链接」时，弹出的「缩略视图」中只展示 <code>#话题</code> 所包含的内容（最新版本不再展示全文），并且点击「双向链接」也会直接跳转到对应的话题所在行。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513529.png" alt="img"></p><h3 id="超链接语法-别名引用"><a href="#超链接语法-别名引用" class="headerlink" title="超链接语法 - 别名引用"></a>超链接语法 - 别名引用</h3><p>别名引用的语法是<code>[[Note Name | Alias]]</code>，即在使用「双向链接」的时候，我们可以在输入的「笔记名称」后边输入一个「别名」，这种「双向链接」的添加方式称为「别名引用」。 </p><p><img src= "/img/loading.gif" data-lazy-src="16046439513540.png" alt="img"></p><p>别名引用带来的好处是，可以更准确的「表述」我们在原笔记中输入「双向链接」时想表达的意思。</p><h3 id="超链接语法-嵌入引用"><a href="#超链接语法-嵌入引用" class="headerlink" title="超链接语法 - 嵌入引用"></a>超链接语法 - 嵌入引用</h3><p>嵌入引用的语法<code>![[Note Name]]</code>，即在使用「双向链接」的时候，我们可以在「双向链接」前边输入一个<code>!</code>（叹号），这种「双向链接」的添加方式称为「嵌入引用」。</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513552.png" alt="img"></p><p>嵌入引用带来的好处是，我们无需跳转，直接在原笔记中查看到被引入的「新笔记」。</p><h3 id="超链接语法-块引用"><a href="#超链接语法-块引用" class="headerlink" title="超链接语法 - 块引用"></a>超链接语法 - 块引用</h3><p>块引用的语法 <code>[[Note Name ^]]</code> ，既在使用「双向链接」的时候，我们可以在「双向链接」的后边输入 <code>^</code> ，此时我们可以将被链接的笔记中的某一行（包括它的从属段落）引入到当前笔记中。这种方式成为「块引用」。</p><p>块引用带来的好处是，我们可以将一篇笔记中的「某个段落」引入到当前笔记中，结合「别名引用」更容易帮我们表达它的意思，如图：</p><p><img src= "/img/loading.gif" data-lazy-src="16046439513563.png" alt="img"></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>本篇作为「玩转 Obsidian」的基础入门介绍，希望能够让更多的人认识并使用它，也是得力于开发者持续不断的迭代更新，我个人非常喜欢 Obsidian ，并打算长期使用并体验，后续会我也会持续更新「玩转 Obsidian」系列文章，也欢迎大家持续关注。</p><blockquote><p>Ctrl+O 打开快速切换</p><p>Ctrl+P 打开命令面板</p></blockquote>]]></content>
      
      
      
    </entry>
    
    
    
    <entry>
      <title>面试必问的`Redis`,你掌握多少？</title>
      <link href="database/redis/redis-interview-01/"/>
      <url>database/redis/redis-interview-01/</url>
      
        <content type="html"><![CDATA[<h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p><code>Redis</code> 是速度非常快的非关系型（NoSQL）内存键值数据库，可以存储键和五种不同类型的值之间的映射。</p><p>键的类型只能为字符串，值支持五种数据类型：字符串、列表、集合、散列表、有序集合。</p><p><code>Redis</code> 支持很多特性，例如将内存中的数据持久化到硬盘中，使用复制来扩展读性能，使用分片来扩展写性能。</p><h2 id="1、Redis支持多种类型的数据结构"><a href="#1、Redis支持多种类型的数据结构" class="headerlink" title="1、Redis支持多种类型的数据结构"></a>1、<code>Redis</code>支持多种类型的数据结构</h2><p>1）.string：最基本的数据类型，二进制安全的字符串，最大512M。<br>2）.list：按照添加顺序保持顺序的字符串列表。<br>3）.set：无序的字符串集合，不存在重复的元素。<br>4）.sorted set：已排序的字符串集合。<br>5）.hash：key-value对的一种集合。</p><p><img src= "/img/loading.gif" data-lazy-src="640.webp" alt="图片"></p><p><strong>具体操作，看这篇文章：</strong>[<strong>[基础] PHP操作Redis，多操作几次你就会了</strong>](<a href="http://mp.weixin.qq.com/s?__biz=MzIxMDA0OTcxNA==&amp;mid=2654262356&amp;idx=2&amp;sn=99e16c11be6abe9ba7a45fed2141415d&amp;chksm=8caafb89bbdd729f8c1cfb5d6ae0650dc47e741e3538f10e29e09fdb454ca27f94b2fedba8ce&amp;scene=21#wechat_redirect">http://mp.weixin.qq.com/s?__biz=MzIxMDA0OTcxNA==&amp;mid=2654262356&amp;idx=2&amp;sn=99e16c11be6abe9ba7a45fed2141415d&amp;chksm=8caafb89bbdd729f8c1cfb5d6ae0650dc47e741e3538f10e29e09fdb454ca27f94b2fedba8ce&amp;scene=21#wechat_redirect</a>)</p><h2 id="2-使用Redis的优势？"><a href="#2-使用Redis的优势？" class="headerlink" title="2 使用Redis的优势？"></a>2 使用<code>Redis</code>的优势？</h2><p><strong>速度快</strong>，因为数据存在内存中，类似于HashMap，HashMap的优势就是查找和操作的时间复杂度都是O(1)</p><p><strong>支持丰富数据类型</strong>，支持string，list，set，sorted set，hash</p><p><strong>支持事务</strong>，操作都是原子性，所谓的原子性就是对数据的更改要么全部执行，要么全部不执行</p><p><strong>丰富的特性</strong>：可用于缓存，消息，按key设置过期时间，过期后将会自动删除</p><h2 id="3-Redis单点吞吐量"><a href="#3-Redis单点吞吐量" class="headerlink" title="3 Redis单点吞吐量"></a>3 <code>Redis</code>单点吞吐量</h2><p>单点TPS达到8万/秒，QPS达到10万/秒，补充下TPS和QPS的概念</p><p>QPS: 应用系统每秒钟最大能接受的用户访问量<br>每秒钟处理完请求的次数，注意这里是处理完，具体是指发出请求到服务器处理完成功返回结果。可以理解在server中有个counter，每处理一个请求加1，1秒后counter=QPS。</p><p>TPS： 每秒钟最大能处理的请求数<br>每秒钟处理完的事务次数，一个应用系统1s能完成多少事务处理，一个事务在分布式处理中，可能会对应多个请求，对于衡量单个接口服务的处理能力，用QPS比较合理。</p><h2 id="4-Redis相比memcached有哪些优势？"><a href="#4-Redis相比memcached有哪些优势？" class="headerlink" title="4 Redis相比memcached有哪些优势？"></a>4 <code>Redis</code>相比memcached有哪些优势？</h2><p>1.memcached所有的值均是简单的字符串，<code>Redis</code>作为其替代者，支持更为丰富的数据类型<br>2.<code>Redis</code>的速度比memcached快很多<br>3.<code>Redis</code>可以持久化其数据<br>4.<code>Redis</code>支持数据的备份，即master-slave模式的数据备份。</p><h2 id="5-Redis有哪几种数据淘汰策略？"><a href="#5-Redis有哪几种数据淘汰策略？" class="headerlink" title="5 Redis有哪几种数据淘汰策略？"></a>5 <code>Redis</code>有哪几种数据淘汰策略？</h2><p>在<code>Redis</code>中，允许用户设置最大使用内存大小server.maxmemory，当<code>Redis</code> 内存数据集大小上升到一定大小的时候，就会施行数据淘汰策略。</p><p>1.volatile-lru:从已设置过期的数据集中挑选最近最少使用的淘汰<br>2.volatile-ttr:从已设置过期的数据集中挑选将要过期的数据淘汰<br>3.volatile-random:从已设置过期的数据集中任意挑选数据淘汰<br>4.allkeys-lru:从数据集中挑选最近最少使用的数据淘汰<br>5.allkeys-random:从数据集中任意挑选数据淘汰<br>6.noenviction:禁止淘汰数据，<code>Redis</code>淘汰数据时还会同步到aof</p><p>作为内存数据库，出于对性能和内存消耗的考虑，<code>Redis</code> 的淘汰算法实际实现上并非针对所有 key，而是抽样一小部分并且从中选出被淘汰的 key。</p><p>使用 <code>Redis</code> 缓存数据时，为了提高缓存命中率，需要保证缓存数据都是热点数据。可以将内存最大使用量设置为热点数据占用的内存量，然后启用 allkeys-lru 淘汰策略，将最近最少使用的数据淘汰。</p><p><code>Redis</code> 4.0 引入了 volatile-lfu 和 allkeys-lfu 淘汰策略，LFU 策略通过统计访问频率，将访问频率最少的键值对淘汰。</p><h2 id="6-Redis提供了哪几种持久化方式？"><a href="#6-Redis提供了哪几种持久化方式？" class="headerlink" title="6 Redis提供了哪几种持久化方式？"></a>6 <code>Redis</code>提供了哪几种持久化方式？</h2><p>1）RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储。<br>2）AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以<code>Redis</code>协议追加保存每次写的操作到文件末尾。</p><p><code>Redis</code>还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。<br>如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。</p><p>你也可以同时开启两种持久化方式, 在这种情况下, 当<code>Redis</code>重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。</p><h2 id="7-如何选择合适的持久化方式？"><a href="#7-如何选择合适的持久化方式？" class="headerlink" title="7 如何选择合适的持久化方式？"></a>7 如何选择合适的持久化方式？</h2><p><code>Redis</code>主要提供了两种持久化机制：RDB和AOF</p><p><strong>RDB：</strong>默认开启，会按照配置的指定时间将内存中的数据快照到磁盘中，创建一个dump.rdb文件，<code>Redis</code>启动时再恢复到内存中。</p><p><code>Redis</code>会单独创建fork()一个子进程，将当前父进程的数据库数据复制到子进程的内存中，然后由子进程写入到临时文件中，持久化的过程结束了，再用这个临时文件替换上次的快照文件，然后子进程退出，内存释放。</p><p>需要注意的是，每次快照持久化都会将主进程的数据库数据复制一遍，导致内存开销加倍，若此时内存不足，则会阻塞服务器运行，直到复制结束释放内存；</p><p>都会将内存数据完整写入磁盘一次，所以如果数据量大的话，而且写操作频繁，必然会引起大量的磁盘I/O操作，严重影响性能，并且最后一次持久化后的数据可能会丢失；</p><p><strong>AOF：</strong>以日志的形式记录每个写操作（读操作不记录），只需追加文件但不可以改写文件，<code>Redis</code>启动时会根据日志从头到尾全部执行一遍以完成数据的恢复工作。包括flushDB也会执行。</p><p>主要有两种方式触发：有写操作就写、每秒定时写（也会丢数据）。</p><p>因为AOF采用追加的方式，所以文件会越来越大，针对这个问题，新增了重写机制，就是当日志文件大到一定程度的时候，会fork出一条新进程来遍历进程内存中的数据，每条记录对应一条set语句，写到临时文件中，然后再替换到旧的日志文件（类似rdb的操作方式）。默认触发是当aof文件大小是上次重写后大小的一倍且文件大于64M时触发。</p><p>当两种方式同时开启时，<strong>数据恢复<code>Redis</code>会优先选择AOF恢复</strong>。一般情况下，只要使用默认开启的RDB即可，因为相对于AOF，RDB便于进行数据库备份，并且恢复数据集的速度也要快很多。</p><p>开启持久化缓存机制，对性能会有一定的影响，特别是当设置的内存满了的时候，更是下降到几百reqs/s。所以如果只是用来做缓存的话，可以关掉持久化。</p><h2 id="8-Redis的事务"><a href="#8-Redis的事务" class="headerlink" title="8 Redis的事务**"></a>8 <code>Redis</code>的事务**</h2><p>一个事务包含了多个命令，服务器在执行事务期间，不会改去执行其它客户端的命令请求。</p><p>事务中的多个命令被一次性发送给服务器，而不是一条一条发送，这种方式被称为流水线，它可以减少客户端与服务器之间的网络通信次数从而提升性能。</p><p><code>Redis</code> 最简单的事务实现方式是使用 MULTI 和 EXEC 命令将事务操作包围起来。</p><h2 id="9-Redis集群之间是如何复制的？"><a href="#9-Redis集群之间是如何复制的？" class="headerlink" title="9 Redis集群之间是如何复制的？"></a>9 <code>Redis</code>集群之间是如何复制的？</h2><p>通过使用 slaveof host port 命令来让一个服务器成为另一个服务器的从服务器。</p><p>一个从服务器只能有一个主服务器，并且不支持主主复制。</p><h3 id="连接过程"><a href="#连接过程" class="headerlink" title="连接过程"></a><strong>连接过程</strong></h3><p>主服务器创建快照文件，发送给从服务器，并在发送期间使用缓冲区记录执行的写命令。快照文件发送完毕之后，开始向从服务器发送存储在缓冲区中的写命令；</p><p>从服务器丢弃所有旧数据，载入主服务器发来的快照文件，之后从服务器开始接受主服务器发来的写命令；</p><p>主服务器每执行一次写命令，就向从服务器发送相同的写命令。</p><h3 id="主从链"><a href="#主从链" class="headerlink" title="主从链"></a><strong>主从链</strong></h3><p>随着负载不断上升，主服务器可能无法很快地更新所有从服务器，或者重新连接和重新同步从服务器将导致系统超载。</p><p>为了解决这个问题，可以创建一个中间层来分担主服务器的复制工作。中间层的服务器是最上层服务器的从服务器，又是最下层服务器的主服务器。</p><h2 id="10-Redis如何做内存优化？"><a href="#10-Redis如何做内存优化？" class="headerlink" title="10 Redis如何做内存优化？"></a>10 <code>Redis</code>如何做内存优化？</h2><p>尽可能使用散列表（hashes），散列表（是说散列表里面存储的数少）使用的内存非常小，所以你应该尽可能的将你的数据模型抽象到一个散列表里面。</p><p>比如你的web系统中有一个用户对象，不要为这个用户的名称，姓氏，邮箱，密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面.</p><h2 id="11-Redis回收进程如何工作的？"><a href="#11-Redis回收进程如何工作的？" class="headerlink" title="11 Redis回收进程如何工作的？"></a>11 <code>Redis</code>回收进程如何工作的？</h2><p>一个客户端运行了新的命令，添加了新的数据。</p><p>Redi检查内存使用情况，如果大于maxmemory的限制, 则根据设定好的策略进行回收。</p><h2 id="12-使用过Redis分布式锁么，它是什么回事？"><a href="#12-使用过Redis分布式锁么，它是什么回事？" class="headerlink" title="12 使用过Redis分布式锁么，它是什么回事？"></a>12 使用过<code>Redis</code>分布式锁么，它是什么回事？</h2><p>先拿setnx来争抢锁，抢到之后，再用expire给锁加一个过期时间防止锁忘记了释放。</p><p>这时候对方会告诉你说你回答得不错，然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了，那会怎么样？</p><p>这时候你要给予惊讶的反馈：唉，是喔，这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋，故作思考片刻，好像接下来的结果是你主动思考出来的。</p><p>然后回答：我记得set指令有非常复杂的参数，这个应该是可以同时把setnx和expire合成一条指令来用的！对方这时会显露笑容，心里开始默念：嗯，这小子还不错。</p><h2 id="13-Redis里面有1亿个key，其中有10w个key是以某个固定的已知的前缀开头的，如何将它们全部找出来？"><a href="#13-Redis里面有1亿个key，其中有10w个key是以某个固定的已知的前缀开头的，如何将它们全部找出来？" class="headerlink" title="13 Redis里面有1亿个key，其中有10w个key是以某个固定的已知的前缀开头的，如何将它们全部找出来？"></a>13 <code>Redis</code>里面有1亿个key，其中有10w个key是以某个固定的已知的前缀开头的，如何将它们全部找出来？</h2><p>使用keys指令可以扫出指定模式的key列表。</p><p>对方接着追问：如果这个<code>Redis</code>正在给线上的业务提供服务，那使用keys指令会有什么问题？</p><p>这个时候你要回答<code>Redis</code>关键的一个特性：<code>Redis</code>的单线程的。keys指令会导致线程阻塞一段时间，线上服务会停顿，直到指令执行完毕，服务才能恢复。</p><p>这个时候可以使用scan指令，scan指令可以无阻塞的提取出指定模式的key列表，但是会有一定的重复概率，在客户端做一次去重就可以了，但是整体所花费的时间会比直接用keys指令长。</p><h2 id="14-使用过Redis做异步队列么，你是怎么用的？"><a href="#14-使用过Redis做异步队列么，你是怎么用的？" class="headerlink" title="14 使用过Redis做异步队列么，你是怎么用的？"></a>14 使用过<code>Redis</code>做异步队列么，你是怎么用的？</h2><p>一般使用list结构作为队列，rpush生产消息，lpop消费消息。当lpop没有消息的时候，要适当sleep一会再重试。</p><p><strong>如果对方追问可不可以不用sleep呢？</strong>list还有个指令叫blpop，在没有消息的时候，它会阻塞住直到消息到来。</p><p><strong>如果对方追问能不能生产一次消费多次呢？</strong>使用pub/sub主题订阅者模式，可以实现1:N的消息队列。</p><p><strong>如果对方追问pub/sub有什么缺点？</strong>在消费者下线的情况下，生产的消息会丢失，得使用专业的消息队列如Rabbitmq等。</p><p><strong>如果对方追问<code>Redis</code>如何实现延时队列？</strong>我估计现在你很想把面试官一棒打死。如果你手上有一根棒球棍的话，怎么问的这么详细。但是你很克制，然后神态自若的回答道：使用sortedset，拿时间戳作为score，消息内容作为key调用zadd来生产消息，消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。</p><h2 id="15-如果有大量的key需要设置同一时间过期，一般需要注意什么？"><a href="#15-如果有大量的key需要设置同一时间过期，一般需要注意什么？" class="headerlink" title="15 如果有大量的key需要设置同一时间过期，一般需要注意什么？"></a>15 如果有大量的key需要设置同一时间过期，一般需要注意什么？</h2><p>如果大量的key过期时间设置的过于集中，到过期的那个时间点，<code>Redis</code>可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值，使得过期时间分散一些。</p><h2 id="16-Redis的同步机制了解么？"><a href="#16-Redis的同步机制了解么？" class="headerlink" title="16 Redis的同步机制了解么？"></a>16 <code>Redis</code>的同步机制了解么？</h2><p><strong>从从同步。</strong>第一次同步时，主节点做一次bgsave，并同时将后续修改操作记录到内存buffer，待完成后将rdb文件全量同步到复制节点，复制节点接受完成后将rdb镜像加载到内存。</p><p>加载完成后，再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。</p><h2 id="17-Reids哈希冲突，如何解决？"><a href="#17-Reids哈希冲突，如何解决？" class="headerlink" title="17 Reids哈希冲突，如何解决？"></a>17 Reids哈希冲突，如何解决？</h2><h3 id="1-线性探测法："><a href="#1-线性探测法：" class="headerlink" title="1.线性探测法："></a>1.线性探测法：</h3><p>如果hash函数计算得出的存储位置一杯占用，那么将继续向后寻找空间的位置进行存放</p><p>缺点：hash一旦冲突，将会增加查询的时间复杂度，由原来的O(1)转化成O(n)，hash冲出越多，效率越低</p><p>随着hash表越来越满，哈希冲的概率就越大，所以的哈希表都有一个衡量因子，即加载因子（loadfactor = 0.75）</p><p>公式： 以占有的hash位置 / 总的hash位置 &gt; loadfactor O(1)</p><h3 id="2-链地址法-拉链法-："><a href="#2-链地址法-拉链法-：" class="headerlink" title="2.链地址法(拉链法)："></a>2.链地址法(拉链法)：</h3><p>把哈希冲突冲突的元素都放在一个链表中，但是链表的长度不能太长，越长效率越慢</p><p>时刻关注哈希表的loadfactor加载因子，如果查过及时进行扩容操作，扩容后原来表的hash数据，需要重新hash</p><p>如图：</p><p><img src= "/img/loading.gif" data-lazy-src="640-1616417574130.webp" alt="图片"></p><p> <strong>文章来自：<a href="https://blog.csdn.net/weixin_36380516/article/details/107171865">https://blog.csdn.net/weixin_36380516/article/details/107171865</a></strong></p><p><em><strong>*以上是本文的全部内容，希望对大家的学习有帮助，觉得有用，有需要就支持一下吧*</strong></em></p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> Linux </tag>
            
            <tag> nosql </tag>
            
            <tag> Redis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据结构与算法</title>
      <link href="unclass/data_algorithm/"/>
      <url>unclass/data_algorithm/</url>
      
        <content type="html"><![CDATA[<p>稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)等。</p><script>window.location.href='https://victorfengming.gitee.io/data_algorithm/';</script>]]></content>
      
      
      
        <tags>
            
            <tag> summer </tag>
            
            <tag> java </tag>
            
            <tag> algorithm </tag>
            
            <tag> 数据结构 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java设计模式</title>
      <link href="unclass/design_pattern/"/>
      <url>unclass/design_pattern/</url>
      
        <content type="html"><![CDATA[<p>设计模式(英语 design pattern)是对面向对象设计中反复出现的问题的解决方案。这个术语是在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来的。</p><p>这个术语的含义还存有争议。算法不是设计模式，因为算法致力于解决问题而非设计问题。设计模式通常描述了一组相互紧密作用的类与对象。</p><script>window.location.href='https://victorfengming.gitee.io/design_pattern/';</script>]]></content>
      
      
      
        <tags>
            
            <tag> summer </tag>
            
            <tag> java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>笔记本关闭自带键盘的方法</title>
      <link href="unclass/close-keyboard/"/>
      <url>unclass/close-keyboard/</url>
      
        <content type="html"><![CDATA[<h2 id="说在前面"><a href="#说在前面" class="headerlink" title="说在前面"></a>说在前面</h2><p>很多小伙伴在使用笔记本的时候不喜欢使用笔记本自带的键盘,</p><p>然后连接外置键盘的时候,又可能会误触到原来的键盘</p><p>下面小编教搭建如何关闭笔记本的自带键盘(可恢复)</p><h2 id="方式一"><a href="#方式一" class="headerlink" title="方式一"></a>方式一</h2><p>首先在笔记本电脑桌面的“计算机（我的电脑）”上右键鼠标，然后选择打开“属性”，如下图所示。</p><p>2<br>打开系统属性后，点击进入上角的【设备管理器】，如下图所示。</p><p>3<br>打开笔记本设备管理器之后，找到【键盘】，点击展开，然后在【PS/2标准键盘】上右键鼠标，然后选择【更新驱动程序软件】，如下示意图所示。</p><p>4<br>在接下来的您如何搜索驱动程序软件界面，点击【浏览计算机一查找驱动程序软件】，如下图所示。</p><p>5<br>之后会进入浏览计算机上的驱动程序文件选择界面，这里依旧点击底部的【从计算机的设备驱动程序列表中选择】，如下图所示。</p><p>6<br>下面的这步“选择要为此硬件安装的设备驱动程序”设置非常重要，首先要将【显示兼容硬件】前面的勾去掉，然后在厂商里，任意选择一个其他笔记本品牌，比如笔者用的是联想笔记本，在这里我们故意选择“宏碁（Acer）”厂商，然后在右侧的型号里，任意选择一个，完成后点击下面的【下一步】，如下图所示。</p><p>7<br>最后会弹出一个“不推荐安装这个设备的驱动程序），因为Window无法验证这个驱动程序是否与硬件兼容…”，这里我们直接点击底部的【是】，如下图所示。</p><p>8<br>以上步骤完成后，我们就可以完成禁用笔记本自带键盘了，可能大家会觉得怎么操作之后，笔记本键盘还能使用，别着急，还差最后一步，需要重启笔记本才会生效。</p><hr><p>原文链接:<a href="https://jingyan.baidu.com/article/60ccbceb639d2364cab19799.html">https://jingyan.baidu.com/article/60ccbceb639d2364cab19799.html</a></p><h2 id="方式二"><a href="#方式二" class="headerlink" title="方式二"></a>方式二</h2><p>1.管理员运行cmd</p><p>2.运行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sc config i8042prt start&#x3D;disabled</span><br></pre></td></tr></table></figure><p>3.重启</p><hr><blockquote><p>win10 1803亲测可用。</p></blockquote><p>但是注意这里有个坑，网上能搜到的教你恢复的方法都是不管用的，最起码win10下不管用，</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sc config i8042prt start&#x3D;auto</span><br></pre></td></tr></table></figure><p>是恢复不了的，要用</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sc config i8042prt start&#x3D;demand</span><br></pre></td></tr></table></figure><p>才行。</p><p>对应的注册表位置：<code>[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt]&quot;Start&quot;=dword:00000003</code></p><p>// 对应start= demand，服务类型：手动<code>&quot;Start&quot;=dword:00000004</code>     </p><p>// 对应start= disabled，服务类型：禁用</p><p>原文链接：<a href="https://www.zhihu.com/question/36434420/answer/453941619">https://www.zhihu.com/question/36434420/answer/453941619</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>vue2-vue3对比</title>
      <link href="front/vue/vue2-vue3/"/>
      <url>front/vue/vue2-vue3/</url>
      
        <content type="html"><![CDATA[<p>Vue2和Vue3的相比较而言的相关面试题</p><ol><li>抱歉:Vue3没有研究那么深,不知道</li><li>2020年9月发布的正式版</li></ol><p>Vue3支持大多数的Vue2的特性</p><p>Vue中设计了一套强大的组合Api代替了Vue2中的option API,复用性更强了<br>更好的支持TS</p><ul><li>最主要:Vue3中使用了Proxy配合Reflect 代替了Vue2中Object.defineProperty()方法<br>  实现了数据的响应式(数据代理)</li><li>重写了虚拟DOM,速度更快了</li><li>新的组件: Fragment(片段) / Teleport(瞬移) / Suspense(不确定)</li><li>设计了一个新的脚手架工具,vite    </li></ul>]]></content>
      
      
      
    </entry>
    
    
    
    <entry>
      <title>Python脚本实现爬取哔哩哔哩壁纸</title>
      <link href="python/spider/spider-for-bilibili/"/>
      <url>python/spider/spider-for-bilibili/</url>
      
        <content type="html"><![CDATA[<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">爬虫</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">爬取 哔哩哔哩中 的领克壁纸</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>():</span></span><br><span class="line"></span><br><span class="line">    url = <span class="string">&quot;https://www.bilibili.com/read/cv8222028&quot;</span></span><br><span class="line"></span><br><span class="line">    meizi_html = requests.get(url).text</span><br><span class="line"></span><br><span class="line">    <span class="comment"># print(meizi_html)</span></span><br><span class="line">    patt = <span class="string">&quot;data-src=\&quot;//i0.hdslb.com/bfs/article/(.*?.\w\wg)\&quot; width&quot;</span></span><br><span class="line">    src_list = re.findall(patt,meizi_html)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># src = src_list.group(0)</span></span><br><span class="line"></span><br><span class="line">    i = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> src <span class="keyword">in</span> src_list:</span><br><span class="line">        i+=<span class="number">1</span></span><br><span class="line">        image_url = <span class="string">&quot;http://i0.hdslb.com/bfs/article/&quot;</span>+src</span><br><span class="line">        download(image_url,<span class="string">&quot;./lynk/&quot;</span>,<span class="built_in">str</span>(i)+image_url[-<span class="number">4</span>:])</span><br><span class="line">        print(src)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">download</span>(<span class="params">image_url,dir_path,file_name</span>):</span></span><br><span class="line">    r = requests.get(image_url)</span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(dir_path+file_name, <span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">        f.write(r.content)</span><br><span class="line"><span class="comment"># 测试可用</span></span><br><span class="line"><span class="comment"># download(&quot;http://i0.hdslb.com/bfs/article/1fff23a7966b36b1ccb13c6203006969fedaf3b5.jpg&quot;,&quot;./&quot;,&quot;demo01.jpg&quot;)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">main()</span><br><span class="line"></span><br></pre></td></tr></table></figure><blockquote><p>在第一次获取到页面,最好先保存一下HTML,免得被封掉</p></blockquote>]]></content>
      
      
      
    </entry>
    
    
    
    <entry>
      <title>使用正则表达式替换博客模板中的tags标签</title>
      <link href="python/self_tool/regex-replace-tags/"/>
      <url>python/self_tool/regex-replace-tags/</url>
      
        <content type="html"><![CDATA[<p>事情是这样的</p><p>小编原来的博客是jeklly格式的模板</p><p>所以tag是用空格区分的,类似这样的</p><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210305231310.png"></p><p>而新的hexo的格式要求是这样的</p><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210305231321.png"></p><p>正则表达式如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(\ntags:.*) (\w+)\n</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$1\n\t- $2\n</span><br></pre></td></tr></table></figure><p>匹配思路为从后面一个tag开始替换,直到替换完所有tags</p><p>然后,在idea中批量替换,就可以了,多点几次</p><p>你点的次数就是,含有最多tag的一篇文章的数量</p><p><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210305231151.png"><br><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210305231157.png"><br><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210305231203.png"></p><p>查看一下一共替换了文件 319个,这要是让我一下一下改,这还不得改到死</p><p><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210305231837.jpg"></p><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210305231125.png"></p><blockquote><p>你以为这就完了</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(\ntags:.*   \w+) +\n</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$1\n</span><br></pre></td></tr></table></figure><p>有的tag后面有空格</p><p>需要先去掉</p><p>一下吓一跳,还有这么多没替换呢</p><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210305232555.png"></p><p>然后重复执行前面的操作</p><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210305232828.png"></p><p>继续替换</p><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210305232850.png"></p><p>知道他没有查询到匹配的内容</p><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210305232915.png"></p><p>然后你以为这样就结束了?</p><p>我又发现我还有中文的tag</p><p>所以我又优化了一个版本</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(\ntags:.*) (\S+)\n</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$1\n\t- $2\n</span><br></pre></td></tr></table></figure><p>这回可真的没了</p>]]></content>
      
      
      
        <tags>
            
            <tag> regex </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>java虚拟机的内存分配和垃圾回收</title>
      <link href="java/jvm/jvm-memory-garbage/"/>
      <url>java/jvm/jvm-memory-garbage/</url>
      
        <content type="html"><![CDATA[<h2 id="1-为什么会有JAVA虚拟机？"><a href="#1-为什么会有JAVA虚拟机？" class="headerlink" title="1.为什么会有JAVA虚拟机？"></a>1.为什么会有JAVA虚拟机？</h2><p>java源程序.java文件经过javac编译成.class文件，.class文件将由java虚拟机，解释成机器码（不同平台的机器码不同），利用机器码操作硬件和操作系统</p><h2 id="2-什么是JAVA虚拟机？"><a href="#2-什么是JAVA虚拟机？" class="headerlink" title="2.什么是JAVA虚拟机？"></a>2.什么是JAVA虚拟机？</h2><p>java虚拟机是执行.class（字节码）文件的虚拟（机）程序进程，ps:我自己把它理解成window系统的一个进程,这个进程其实就相当于一个虚拟机（java虚拟机）</p><h2 id="3-为什么我们要学习JAVA虚拟机"><a href="#3-为什么我们要学习JAVA虚拟机" class="headerlink" title="3.为什么我们要学习JAVA虚拟机"></a>3.为什么我们要学习JAVA虚拟机</h2><p>日常的的开发中，我们只关注于写java代码，而并没有关心java虚拟机的相关操作，而未了进一步提升自己，对Java语言的深入理解，并对未来的如果出现内存溢出等问题奠定基础，还有个目的是为了面试(^o^)/ </p><h2 id="4-JAVA虚拟机的体系结构"><a href="#4-JAVA虚拟机的体系结构" class="headerlink" title="4.JAVA虚拟机的体系结构"></a>4.JAVA虚拟机的体系结构</h2><p><img src= "/img/loading.gif" data-lazy-src="20190810220710364.jpg" alt="img"></p><p>图中画区域的是所有线程所共享的（方法区，堆，执行引擎，本地接口）</p><h3 id="方法区"><a href="#方法区" class="headerlink" title="方法区"></a>方法区</h3><p>方法区（Method Area）：方法区是各个线程共享的区域，用于存储已经被虚拟机加载的类信息（即加载类时需要加载的信息，包括版本、field、方法、接口等信息）、final常量、静态变量、编译器即时编译的代码等。</p><p>关于方法区不太理解的，我稍后写些例子。。。。</p><h3 id="堆"><a href="#堆" class="headerlink" title="堆"></a>堆</h3><p>堆（heap）:也叫java堆。在JVM所管理的内存中，堆区是最大的一块，堆区也是Java GC机制所管理的主要内存区域，堆区由所有线程共享，在虚拟机启动时创建。堆区的存在是为了存储对象实例，原则上讲，所有的对象都在堆区上分配内存。比如new出来的对象、方法的成员变量。</p><p>一般的，根据Java虚拟机规范规定，堆内存需要在逻辑上是连续的（在物理上不需要），在实现时，可以是固定大小的，也可以是可扩展的，目前主流的虚拟机都是可扩展的。如果在执行垃圾回收之后，仍没有足够的内存分配，也不能再扩展，将会抛出OutOfMemoryError:Java heap space异常。</p><h3 id="虚拟机栈"><a href="#虚拟机栈" class="headerlink" title="虚拟机栈"></a>虚拟机栈</h3><p>虚拟机栈（JVM Stack）：也叫java栈。一个线程的每个方法在执行的同时，都会创建一个栈帧（Statck Frame），栈帧中存储的有局部变量表、操作站、动态链接、方法出口等，当方法被调用时，栈帧在JVM栈中入栈，当方法执行完成时，栈帧出栈。</p><p>局部变量表中存储着方法的相关局部变量，包括各种基本数据类型，对象的引用，返回地址等。在局部变量表中，只有long和double类型会占用2个局部变量空间（Slot，对于32位机器，一个Slot就是32个bit），其它都是1个Slot。需要注意的是，局部变量表是在编译时就已经确定好的，方法运行所需要分配的空间在栈帧中是完全确定的，在方法的生命周期内都不会改变。</p><p>　　虚拟机栈中定义了两种异常，如果线程调用的栈深度大于虚拟机允许的最大深度，则抛出StatckOverFlowError（栈溢出）；不过多数Java虚拟机都允许动态扩展虚拟机栈的大小(有少部分是固定长度的)，所以线程可以一直申请栈，直到内存不足，此时，会抛出OutOfMemoryError（内存溢出）。</p><p>　　每个线程对应着一个虚拟机栈，因此虚拟机栈也是线程私有的。</p><h3 id="本地方法区"><a href="#本地方法区" class="headerlink" title="本地方法区"></a>本地方法区</h3><p>本地方法区（Native Method Statck）：本地方法栈在作用，运行机制，异常类型等方面都与虚拟机栈相同，唯一的区别是：虚拟机栈是执行Java方法的，而本地方法栈是用来执行native方法的，在很多虚拟机中（如Sun的JDK默认的HotSpot虚拟机），会将本地方法栈与虚拟机栈放在一起使用。</p><p>本地方法栈也是线程私有的。</p><h3 id="程序计数器"><a href="#程序计数器" class="headerlink" title="程序计数器"></a>程序计数器</h3><p>程序计数器（Program Counter Register）：程序计数器是一个比较小的内存区域，用于指示当前线程所执行的字节码执行到了第几行，可以理解为是当前线程的行号指示器。字节码解释器在工作时，会通过改变这个计数器的值来取下一条语句指令。</p><p>　　每个程序计数器只用来记录一个线程的行号，所以它是线程私有（一个线程就有一个程序计数器）的。</p><p>　　如果程序执行的是一个Java方法，则计数器记录的是正在执行的虚拟机字节码指令地址；如果正在执行的是一个本地（native，由C语言编写完成）方法，则计数器的值为Undefined，由于程序计数器只是记录当前指令地址，所以不存在内存溢出的情况，因此，程序计数器也是所有JVM内存区域中唯一一个没有定义OutOfMemoryError的区域。</p><h2 id="5-为什么要进行垃-圾回收"><a href="#5-为什么要进行垃-圾回收" class="headerlink" title="5**.为什么要进行垃**圾回收"></a>5**.为什么要进行垃**圾回收</h2><p>   程序在进行方法调用的时候，在堆中不停的开辟内存，直到内存OutOfMemoryError（内存溢出）。</p><h2 id="6-什么对象需要垃圾回收"><a href="#6-什么对象需要垃圾回收" class="headerlink" title="6.什么对象需要垃圾回收"></a><strong>6.什么对象需要垃圾回收</strong></h2><p>Java堆和方法区是“线程共享”的，随着虚拟机的启动而存在，这部分内存的分配和回收是动态的，我们只有在程序运行时才知道创建了哪些对象，需要多少内存，GC针对的就是这部分内存的回收                                                                                         </p><p>java栈，本地方法栈，程序计数器都是线程私有的，随着线程生而生，灭而灭，所以不参与垃圾回收</p><ol><li>当程序运行时，首先通过类装载器加载字节码文件，经过解析后装入方法区！在方法区中存了类的各种信息，包括类变量、类常量及方法。对于同一个方法的调用，同一个类的不同实例调用的都是存在方法区的同一个方法。类变量的生命周期从程序开始运行时创建，到程序终止运行时结束！ </li><li>当程序中new一个对象时，这个对象存在堆中，对象的变量存在栈中，指向堆中的引用！对象的成员变量都存在堆中，当对象被回收时，对象的成员变量随之消失！ </li><li>当方法调用时，JVM会在栈中分配一个栈桢，存储方法的局部变量。当方法调用结束时，局部变量消失！</li></ol><p>类变量：属于类的属性信息，与类的实例无关，多个实例共用同一个类变量，存在与方法区中。类变量用static修饰，包括静态变量和常量。静态变量有默认初始值，常量必须声明同时初始化。成员变量：属于实例的变量，只与实例有关，写在类下面，方法外，非static修饰。成员变量会随着成员的创建而生存，随着成员的回收而销毁。</p><p>局部变量：声明在方法中，没有默认初始值，随着方法的调用而创建，存储于栈中，随着方法调用的结束而销毁</p><h2 id="7-什么时间回收"><a href="#7-什么时间回收" class="headerlink" title="7.什么时间回收"></a>7.什么时间回收</h2><p>​    如果对象在申请空间的时候，空间不足，就会触发垃圾回收，如果还有空间，暂时不会进行垃圾回收</p><h2 id="8-如何判断要垃圾回收"><a href="#8-如何判断要垃圾回收" class="headerlink" title="8.如何判断要垃圾回收"></a>8.如何判断要垃圾回收</h2><p>   <strong>引用计数法：</strong>给对象添加一个引用计数器，每当有一个地方引用它，计数器就+1,；当引用失效时，计数器就-1；任何时刻计数器都为0的对象就是不能再被使用</p><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvNGMyODlhMjI0Y2I0OTQ0ZTQ5OWZiNWJmZDMzZTU5MmY_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ.webp" alt="img"></p><p>从图中可以看出，如果不下小心直接把 Obj1-reference 和 Obj2-reference 置 null。则在 Java 堆当中的两块内存依然保持着互相引用无法回收。</p><p><strong>可达性分析算法：</strong>通过一系列的名为“GC Roots”的对象作为起始点，从这些节点开始向下搜索，搜索所走过的路径称为引用链（Reference Chain），当一个对象到 GC Roots 没有任何引用链相连时，则证明此对象是不可用的。</p><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvNThiZmFjMTVjYTZkMzA3NmRlZjUxNzRlZDVjYTVhOTk_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ.webp" alt="img"></p><p>在java中可以作为GC Roots的对象有以下几种：</p><ol><li>虚拟机栈中引用的对象</li><li>方法区中类静态属性引用的对象</li><li>方法区中常量引用的对象</li><li>本地方法栈中JNI（Native方法）引用的对象</li></ol><p> 引用分类</p><p>无论是引用计数法还是可达性分析算法，判断是否存活都与“引用”有关。在JDK1.2之后分为  强引用、软引用、弱引用、虚引用。</p><p>强引用（strong Reference）  就是普通的new对象引用  比如：String str =new String(“hello World”);只要引用一直被调用，jvm哪怕是抛出内存溢出也不会回收这个对象。</p><p>软引用(softReference)  用来描述一些不必须的对象。当jvm内存吃紧的时候，才会回收这个对象，如果内存还是不够，就会抛出内存溢出异常。</p><p>弱引用（weakReference）比软引用还要弱，只要进行垃圾回收，就被回收掉。</p><p>虚引用（PhantomReference ）无法通过虚引用获取一个对象的实例，为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。</p><h1 id="9-垃圾回收算法"><a href="#9-垃圾回收算法" class="headerlink" title="9.垃圾回收算法"></a>9.垃圾回收算法</h1><p> 标记-清除算法（mark-sweep）</p><p>定义：分为标记和清除两个阶段。首先标记出所有需要回收的对象，在标记完成后统一回收被标记的对象。<br>地位：是最基础的垃圾回收算法，后面的几种垃圾回收算法都是基于这种思路并对其不足进行改进而得到的。<br>缺点： </p><ul><li>效率问题。标记和清除过程的效率都不高。 </li><li>空间问题。标记清除之后会产生大量不连续的内存碎片，空间碎片太多可能导致，程序分配较大对象时无法找到足够              的连续内存，不得不提前出发另一次垃圾收集动作。</li></ul><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3BhbndlaWkvTWFya2Rvd25QaG90b3MvbWFzdGVyL0NTRE5CbG9ncy9KVk0vbWFyay1zd2VlcC5wbmc.png" alt="MarkdownPhotos/master/CSDNBlogs/JVM/mark-sweep.png"></p><p><strong>复制算法（copying）</strong></p><p>定义：将可用内存按容量划分为大小相等的两块，每次只使用其中一块。当这一块的内存用完了，就将存活着的对象复制到         另一块上面，然后再把已经使用过的内存空间一次清理掉。<br>优点：解决了标记-清除算法的效率问题。复制算法使得每次都是针对其中的可用内存的半区进行内存回收，内存分配时也           不用考虑内存碎片等复杂情况，只要移动堆顶指针，按顺序分配内存即可，实现简单，运行高效。<br>缺点： </p><ul><li>浪费空间。将内存缩小为原来的一半，代价太高昂。 </li><li>效率问题。在对象存活率较高时，需要执行较多的复制操作，效率会变低。<br>应用：回收新生代<br>  现在的商用虚拟机都采用这种算法来回收新生代。因为新生代中的对象大部分很快就死亡，所以并不需要按照1:1的比例划分内存空间，而是将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间。每次使用 Eden 和其中的一块 Survivor。当回收时，将 Eden 和 Survivor 中还存活的对象一次性拷贝到另外一块 Survivor 空间上，最后清理掉 Eden 和刚才用过的 Survivor 空间。Hotspot 虚拟机默认 Eden 和 Survivor 的大小比例是8:1，也就是每次新生代中可用内存空间为整个新生代容量的90%（80% + 10%），只有10%的内存是会被“浪费”的。当然，无法保证每次回收都只有不多于10%的对象存活，如果10%的Survivor 空间不够用，可以临时使用老年代的内存。</li></ul><p><img src= "/img/loading.gif" data-lazy-src="20190811085633283.png" alt="img"></p><p> <strong>标记整理算法</strong>（mark-compact）</p><p>  定义：标记过程仍然与“标记-清除”算法一样，但后续步骤不是直接对可回收对象进行清理，而是让所有存活的对象向一端移动，然后直接清理掉边界以外的内存。 </p><p> 优点：解决了复制算法的空间和效率问题。<br>  应用：现在的商用虚拟机都采用这种算法来<strong>回收老年代</strong>。 </p><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3BhbndlaWkvTWFya2Rvd25QaG90b3MvbWFzdGVyL0NTRE5CbG9ncy9KVk0vbWFyay1jb21wYWN0LnBuZw.png" alt="MarkdownPhotos/master/CSDNBlogs/JVM/mark-compact.png"></p><p>分代收集算法（Generational Collection）**</p><pre><code>  定义：根据对象的存活周期的不同将内存划分为几块。一般是把 Java 堆分为新生代和老年代，这样就可以根据各个年代的特点，采用最适当的收集算法。对于新生代，每次垃圾收集时会有大批对象死去，只有少量存活，所以选择复制算法，只需要少量存活对象的复制成本就可以完成收集。对于老年代，对象存活率高、没有额外空间对它进行分配担保，必须使用“标记-清理”或“标记-整理”算法进行回收。   优点：可以根据实际情况选择具体的算法   应用：现在的商用虚拟机的垃圾回收都采用这种算法。</code></pre><p>​     </p><p>上面我已经讲到了JAVA垃圾回收针对的主要是java堆的回收，下面说明下java堆的分代回收</p><p><strong>java堆分为，年轻代，老年代，和永久代，在java8中，将永久代替换成了元空间（Metespace）</strong></p><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly93d3cuY29kZXI0LmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxOC8wMy8xLmpwZw.jfif" alt="img"></p><p><strong>新生代</strong><br>主要用来存储新创建的对象，内存较小，MinorGC频繁。新生代又分为三个区域：Eden、ServivorFrom、ServivorTo。<br>Eden：当对象在堆创建时，一般进入Eden。如果新创建的对象占用内存很大，则直接分配到老年代。当Eden区内存不够时会触发MinorGC，对新生代区进行一次垃圾回收。<br>ServivorFrom：上一次GC的幸存者，作为这一次MinorGC的被扫描者。<br>ServivorTo：保留了这一次MinorGC后的幸存者。<br>MinorGC：采用复制算法。 </p><ol><li>扫描Eden和ServivorFrom，将存活的对象复制到ServivorTo，并将这些对象的年龄+1。（如果ServivorTo已经满，则复制到老年代。） </li><li>扫描ServivorFrom时，如果对象已经经过了几次的扫描仍然存活，达到了老年代的标准，JVM会将其移到老年代。 </li><li>扫描完毕后，清空Eden和ServivorFrom，然后交换ServivorFrom和ServivorTo，即ServicorTo成为下一次GC时的ServicorFrom区。</li></ol><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly93d3cuY29kZXI0LmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxOC8wMy8yLmpwZw.jfif" alt="img"></p><p><strong>老年代</strong><br>主要用来存储长时间被引用的对象。它里面存放的是经过几次在新生代进行扫描仍存活的对象。因为老年代对象比较稳定，所以MajorGC频率较小。<br>MajorGC：采用标记-整理算法。</p><p>在进行MajorGC前一般都先进行了一次MinorGC，使得有新生代的对象晋身入老年代，导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次MajorGC进行垃圾回收腾出空间。</p><p>MajorGC的耗时比较长，因为要扫描再回收。MajorGC会产生内存碎片，为了减少内存损耗，我们一般需要进行合并或者标记出来方便下次直接分配。</p><p>当老年代也满了装不下的时候，就会抛出OOM（Out of Memory）异常。</p><p>原文链接：<a href="https://blog.csdn.net/sinat_34454743/article/details/99116013">https://blog.csdn.net/sinat_34454743/article/details/99116013</a></p><p><strong>永久代</strong><br>主要用来存储类元数据信息，如类定义、字节码和常量等。GC不会在主程序运行期对永久代进行清理。Class在被加载的时候被放入永久区域。它和和存放实例的区域不同，GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代会随着加载的Class的增多而胀满，最终抛出OOM异常。在Java8中，永久代已被元空间取代。再启动JVM时，如果JVM设置了PermSize 和 MaxPermSize 两个参数，参数会被忽略并给出警告。</p><p><strong>元空间</strong><br>元空间并不在虚拟机中，而是使用本地内存来存储类元数据信息。因此，默认情况下，元空间的大小仅受本地内存限制。类的元数据放入 native memory, 字符串池和类的静态变量放入java堆中. 这样可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制。</p><pre><code>      注意：堆=新生代+老年代，不包括永久代（方法区）</code></pre><p>很多人认为方法区（或者HotSpot虚拟机中的永久代）是没有垃圾收集的，Java虚拟机规范中确实说过可以不要求虚拟机在方法区实现垃圾收集，而且在方法区进行垃圾收集的“性价比”一般比较低：在堆中，尤其是在新生代中，常规应用进行一次垃圾收集一般可以回收70%~95%的空间，而永久代的垃圾收集效率远低于此。</p><p>永久代的垃圾收集主要回收两部分内容：废弃常量和无用的类。回收废弃常量与回收Java堆中的对象非常类似。以常量池中字面量的回收为例，假如一个字符串“abc”已经进入了常量池中，但是当前系统没有任何一个String对象是叫做“abc”的，换句话说是没有任何String对象引用常量池中的“abc”常量，也没有其他地方引用了这个字面量，如果在这时候发生内存回收，而且必要的话，这个“abc”常量就会被系统“请”出常量池。常量池中的其他类（接口）、方法、字段的符号引用也与此类似。</p><p>判定一个常量是否是“废弃常量”比较简单，而要判定一个类是否是“无用的类”的条件则相对苛刻许多。类需要同时满足下面3个条件才能算是“无用的类”：</p><p>该类所有的实例都已经被回收，也就是Java堆中不存在该类的任何实例。</p><p>加载该类的ClassLoader已经被回收。</p><p>该类对应的java.lang.Class 对象没有在任何地方被引用，无法在任何地方通过反射访问该类的方法。</p><h2 id="10-垃圾收集器"><a href="#10-垃圾收集器" class="headerlink" title="10.垃圾收集器"></a>10.垃圾收集器</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">收集算法是内存回收的理论，而垃圾回收器是内存回收的实践</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvMTVmYjc1NDc2MmZmNWRmM2Y3ZjYzZTVjMjZkNGQzYWU_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ.webp" alt="img"></p><p><strong>Serial 收集器</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这是一个单线程收集器。意味着它只会使用一个 CPU 或一条收集线程去完成收集工作，并且在进行垃圾回收时必须暂停其它所有的工作线程直到收集结束。</span><br></pre></td></tr></table></figure><p>  <img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvYjE4NDk0YjFlNTQ4NTFiYmJkMmVlNTI3NjBjYzM3NTQ_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ" alt="img"></p><p><strong>特性</strong></p><p>针对新生代；<br>采用复制算法；<br>单线程收集：这个收集器是一个单线程的收集器。“单线程”的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作，更重要的是在它进行垃圾收集时，必须暂停其他所有的工作线程，直到它收集结束。<br><strong>应用场景</strong><br>Serial收集器是虚拟机运行在Client模式下的默认新生代收集器。</p><p><strong>优势</strong><br>简单而高效（与其他收集器的单线程比），对于限定单个CPU的环境来说，Serial收集器由于没有线程交互的开销，专心做垃圾收集自然可以获得最高的单线程收集效率。</p><p><strong>参数</strong><br>-XX:+UseSerialGC。Jvm运行在Client模式下的默认值，打开此开关后，使用Serial + Serial Old的收集器组合进行内存回收。</p><p><strong>ParNew收集器</strong></p><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvMTU0NjVmYjJlMTdjYjVkNjY1YzI1YmI5OGFjZmVhOTM_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ.webp" alt="img"></p><p><strong>特性</strong><br>ParNew收集器其实就是Serial收集器的多线程版本，除了使用多条线程进行垃圾收集之外，其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一样，在实现上，这两种收集器也共用了相当多的代码。</p><p><strong>应用场景</strong><br>1.ParNew收集器是许多运行在Server模式下的虚拟机中首选的新生代收集器。<br>除了Serial收集器外，目前只有它能与CMS收集器配合工作。<br>在JDK 1.5时期，HotSpot推出了一款在强交互应用中几乎可认为有划时代意义的垃圾收集器——CMS收集器，这款收集器是HotSpot虚拟机中第一款真正意义上的并发收集器，它第一次实现了让垃圾收集线程与用户线程同时工作。<br>不幸的是，CMS作为老年代的收集器，却无法与JDK 1.4.0中已经存在的新生代收集器Parallel Scavenge配合工作，所以在JDK 1.5中使用CMS来收集老年代的时候，新生代只能选择ParNew或者Serial收集器中的一个。</p><p><strong>优势</strong></p><p>多线程<br>-除了Serial收集器外，目前只有它能与CMS收集器配合工作。<br>参数</p><p>-XX:+UseConcMarkSweepGC：指定使用CMS后，会默认使用ParNew作为新生代收集器<br>-XX:+UseParNewGC：强制指定使用ParNew<br>-XX:ParallelGCThreads：指定垃圾收集的线程数量，ParNew默认开启的收集线程与CPU的数量相同</p><p><strong>Serial收集器与ParNew收集器</strong><br>ParNew收集器在单CPU的环境中绝对不会有比Serial收集器更好的效果，甚至由于存在线程交互的开销，该收集器在通过超线程技术实现的两个CPU的环境中都不能百分之百地保证可以超越Serial收集器。然而，随着可以使用的CPU的数量的增加，它对于GC时系统资源的有效利用还是很有好处的。</p><p>Parallel Scaveage收集器</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这是一个新生代收集器，也是使用复制算法实现，同时也是并行的多线程收集器。</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvMjU2NDEzNjZiNDNkOTcxMzEwYTBhN2NlZGU0ZTQwNmE_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ" alt="img"></p><p><strong>特性</strong></p><p>新生代收集器；<br>采用复制算法；<br>多线程收集；<br>看上去和ParNew收集器一样，它有什么特别之处呢？<br>Parallel Scavenge收集器的特点是它的关注点与其他收集器不同，CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间，而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量（Throughput）。<br>吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值，即吞吐量 = 运行用户代码时间 /（运行用户代码时间 + 垃圾收集时间）。<br>虚拟机总共运行了100分钟，其中垃圾收集花掉1分钟，那吞吐量就是99%。</p><p><strong>应用场景</strong><br>高吞吐量则可以高效率地利用CPU时间，尽快完成程序的运算任务，主要适合在后台运算而不需要太多交互的任务。</p><p><strong>优势</strong><br>参考特性和应用场景。</p><p><strong>参数</strong></p><p>-XX:+UseParallelGC：Jvm运行在Server模式下的默认值，打开此开关后，使用Parallel Scavenge + Serial Old的收集器组合进行回收；<br>-XX:+UseParallelOldGC：使用Parallel Scavenge + Parallel Old的收集器组合进行回收；<br>Parallel Scavenge收集器提供两个参数用于精确控制吞吐量：</p><p>-XX:MaxGCPauseMillis。用于控制最大垃圾收集停顿时间。<br>-XX:GCTimeRatio。设置吞吐量大小<br>-XX:+UseAdaptiveSizePolicy。开启自适应调节策略。<br>————————————————</p><p> <strong>GC自适应的调节策略</strong>  </p><p>Parallel Scavenge收集器有一个参数-XX:+UseAdaptiveSizePolicy。当这个参数打开之后，就不需要手工指定新生代的大小（-Xmn）、Eden与Survivor区的比例（-XX：SurvivorRatio）、晋升老年代对象年龄（-XX：PretenureSizeThreshold）等细节参数了，虚拟机会根据当前系统的运行情况收集性能监控信息，动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量，这种调节方式称为GC自适应的调节策略（GC Ergonomics）。<br>如果对垃圾收集器不太了解，手动优化困难，这是一种值得推荐的方式。</p><p>只需要把基本的内存数据设置好（如-Xmx设置最大堆）；<br>然后使用-XX:MaxGCPauseMillis或-XX:GCTimeRatio给JVM设置一个优化目标；<br>那些具体细节参数的调节就由JVM自适应完成。</p><p><strong>Serial Old收集器</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Serial Old是 Serial收集器的老年代版本</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvYjE4NDk0YjFlNTQ4NTFiYmJkMmVlNTI3NjBjYzM3NTQ_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ.webp" alt="img"></p><p><strong>特性</strong></p><p>针对老年代；<br>采用”标记-整理”算法；<br>单线程收集；<br>应用场景</p><p>Client模式。主要用于Client模式。<br>Server模式。Server模式有两大用途：<br>在JDK1.5及之前的版本中与Parallel Scavenge收集器搭配使用<br>作为CMS收集器的后备预案，在并发收集发生Concurrent Mode Failure时使用。</p><p><strong>参数</strong><br>-XX:+UseSerialGC。Jvm运行在Client模式下的默认值，打开此开关后，使用Serial + Serial Old的收集器组合进行内存回收。 </p><p><strong>Parallel Old收集器</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Parallel Old 是 Parallel Scavenge 收集器的老年代版本。多线程，使用 标记 —— 整理</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvMjU2NDEzNjZiNDNkOTcxMzEwYTBhN2NlZGU0ZTQwNmE_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ.webp" alt="img"></p><p><strong>CMS 收集器</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CMS (Concurrent Mark Sweep) 收集器是一种以获取最短回收停顿时间为目标的收集器。基于 标记 —— 清除 算法实现。</span><br></pre></td></tr></table></figure><p>** <strong>运作步骤</strong> **</p><p> 初始标记(CMS initial mark)：标记 GC Roots 能直接关联到的对象<br>并发标记(CMS concurrent mark)：进行 GC Roots Tracing<br>重新标记(CMS remark)：修正并发标记期间的变动部分<br>并发清除(CMS concurrent sweep)</p><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvNmY0ZDY4MzY0NGExNTQ1MzdiM2UyM2Q2MGQ0OWMwNzQ_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ.webp" alt="img"> </p><p>缺点：对 CPU 资源敏感、无法收集浮动垃圾、<code>标记 —— 清除</code> 算法带来的空间碎片</p><p><strong>G1 收集器</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">面向服务端的垃圾回收器。</span><br></pre></td></tr></table></figure><p>优点：并行与并发、分代收集、空间整合、可预测停顿。</p><p>运作步骤:</p><p>初始标记(Initial Marking)<br>并发标记(Concurrent Marking)<br>最终标记(Final Marking)<br>筛选回收(Live Data Counting and Evacuation)</p><p><img src= "/img/loading.gif" data-lazy-src="aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxNy85LzQvNDBhNTc1OTMxYjI1NGE4ZjQwYmI1NDNjMjRlOGZhZGY_aW1hZ2VWaWV3Mi8wL3cvMTI4MC9oLzk2MC9mb3JtYXQvd2VicC9pZ25vcmUtZXJyb3IvMQ.webp" alt="img"></p><p><strong>垃圾收集器比较</strong></p><p><img src= "/img/loading.gif" data-lazy-src="20190811101310488.png" alt="img"></p><p>上图摘自<a href="https://blog.csdn.net/panweiwei1994/article/details/79111432">https://blog.csdn.net/panweiwei1994/article/details/79111432</a></p><p>垃圾收集器参数总结</p><p>-XX:+<option> 启用选项<br>-XX:-<option> 不启用选项<br>-XX:<option>=<number><br>-XX:<option>=<string></p><p><img src= "/img/loading.gif" data-lazy-src="20190811101505207-1615211442360.png" alt="img"></p><p>上图摘自<a href="https://blog.csdn.net/panweiwei1994/article/details/79111432">https://blog.csdn.net/panweiwei1994/article/details/79111432</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> java </tag>
            
            <tag> jvm </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python实现从文件中读取文件名,并创建文件</title>
      <link href="python/self_tool/python-new-file/"/>
      <url>python/self_tool/python-new-file/</url>
      
        <content type="html"><![CDATA[<h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">根据文件内容,创建文件</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">newFile</span>(<span class="params">file</span>):</span></span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1:</span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line">            print(<span class="string">&quot;==================&quot;</span>)</span><br><span class="line">            <span class="comment"># 新建文件的文件名,最后一行的\n去掉</span></span><br><span class="line">            newName = line[:-<span class="number">1</span>]</span><br><span class="line">            print(newName)</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(newName, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">                f2.write(<span class="string">&quot;#&quot;</span>+line)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">newFile(<span class="string">&quot;D:\\WebstormProjects\\react\\sgg\\README.md&quot;</span>)</span><br></pre></td></tr></table></figure><p>问题分析</p><p>这个创建的文件的位置是在脚本的同级目录,但是我这里想要创建到readme.md文件同级目录中</p><h2 id="升级版本"><a href="#升级版本" class="headerlink" title="升级版本"></a>升级版本</h2><p>获取文件夹路径</p><blockquote><p>os.path.dirname()</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">根据文件内容,创建文件</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">newFile</span>(<span class="params">file</span>):</span></span><br><span class="line">    <span class="comment"># 获取目录</span></span><br><span class="line">    dirname = os.path.dirname(file)</span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1:</span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line">            print(<span class="string">&quot;==================&quot;</span>)</span><br><span class="line">            <span class="comment"># 新建文件的文件名,最后一行的\n去掉</span></span><br><span class="line">            newName = dirname+<span class="string">&quot;\\&quot;</span>+line[:-<span class="number">1</span>]</span><br><span class="line">            print(newName)</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(newName, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">                f2.write(<span class="string">&quot;# &quot;</span>+line)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">newFile(<span class="string">&quot;D:\\WebstormProjects\\react\\sgg\\README.md&quot;</span>)</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                 神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="升级版本-1"><a href="#升级版本-1" class="headerlink" title="升级版本"></a>升级版本</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2021/3/16 21:45&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># coding=utf-8</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line"><span class="comment"># dir 是全路径</span></span><br><span class="line"><span class="comment"># 比如: E:\Projects\PycharmProjects\untitled\test\database\redis\2019-09-25-deepin-install-redis.md</span></span><br><span class="line"><span class="comment"># :param dir:</span></span><br><span class="line"><span class="comment"># :return:</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">repSpilt</span>(<span class="params">path</span>):</span></span><br><span class="line">    <span class="keyword">return</span> path.replace(<span class="string">&quot;\\&quot;</span>,<span class="string">&quot;\\\\&quot;</span>)</span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">根据文件内容,创建文件</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">newFile</span>(<span class="params">file</span>):</span></span><br><span class="line">    <span class="comment"># 获取目录</span></span><br><span class="line">    dirname = os.path.dirname(file)</span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1:</span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line">            print(<span class="string">&quot;=========================================&quot;</span>)</span><br><span class="line">            <span class="comment"># 新建文件的文件名,最后一行的\n去掉</span></span><br><span class="line">            newName = dirname+<span class="string">&quot;\\&quot;</span>+line[:-<span class="number">1</span>]</span><br><span class="line">            print(newName)</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(newName, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">                f2.write(<span class="string">&quot;# &quot;</span>+line[:-<span class="number">3</span>])</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># 获取输入</span></span><br><span class="line">    print(<span class="string">&quot;=========================================&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;md文件生成器,通过读取文件中的行数来创建文件&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;生成的文件会和源文件同目录&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;注意:原有文件会被替换&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;请输入源目录文件路径,window用 \ 来分隔文件夹&quot;</span>)</span><br><span class="line">    sourceFile = <span class="built_in">input</span>(<span class="string">&quot;:&quot;</span>)</span><br><span class="line">    newFile(repSpilt(sourceFile))</span><br><span class="line">    os.system(<span class="string">&#x27;pause&#x27;</span>)</span><br></pre></td></tr></table></figure><h2 id="利用工具-生成-exe-使用"><a href="#利用工具-生成-exe-使用" class="headerlink" title="利用工具 生成 exe 使用"></a>利用工具 生成 exe 使用</h2><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210316212803.png"><br><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210316213741.png"><br><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210316213906.png"></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python实现替换博客文章名中的日期到文件中</title>
      <link href="python/self_tool/python-re-blog-date/"/>
      <url>python/self_tool/python-re-blog-date/</url>
      
        <content type="html"><![CDATA[<h2 id="问题分析"><a href="#问题分析" class="headerlink" title="问题分析"></a>问题分析</h2><p>事情是这样的</p><p>我原来的博客的日期是在文件名中的,而新的模板中的日期是放到了md文件文件头中</p><p>我这几百篇博客当然不能手动修改了,于是小编就利用了一个python中的文件操作和re模块写了一个脚本实现了这个替换功能</p><h2 id="代码如下"><a href="#代码如下" class="headerlink" title="代码如下"></a>代码如下</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2021/3/6 21:05&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># coding=utf-8</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">---</span></span><br><span class="line"><span class="string">title: &quot;Flask 概述&quot;</span></span><br><span class="line"><span class="string">cover: &quot;/img/lynk/93.jpg&quot;</span></span><br><span class="line"><span class="string">date:       2021-03-06</span></span><br><span class="line"><span class="string">tags:</span></span><br><span class="line"><span class="string">    - Python</span></span><br><span class="line"><span class="string">    - solution</span></span><br><span class="line"><span class="string">    - web</span></span><br><span class="line"><span class="string">    - flask</span></span><br><span class="line"><span class="string">---</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">---</span></span><br><span class="line"><span class="string">layout:     keynote</span></span><br><span class="line"><span class="string">title:      &quot;Example Post using Keynote Layout&quot;</span></span><br><span class="line"><span class="string">cover: &quot;/img/lynk/93.jpg&quot;</span></span><br><span class="line"><span class="string">date:       2021-03-06</span></span><br><span class="line"><span class="string">subtitle:   &quot;Keynote: JavaScript Modularization Journey&quot;</span></span><br><span class="line"><span class="string">iframe:     &quot;http://huangxuan.me/js-module-7day/&quot;</span></span><br><span class="line"><span class="string">date:       2015-07-09</span></span><br><span class="line"><span class="string">author:     &quot;Hux&quot;</span></span><br><span class="line"><span class="string">header-img: &quot;post-bg-js-version.jpg&quot;</span></span><br><span class="line"><span class="string">tags:</span></span><br><span class="line"><span class="string">    - 前端开发</span></span><br><span class="line"><span class="string">    - JavaScript</span></span><br><span class="line"><span class="string">---</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">alter</span>(<span class="params">file,old_str,new_str</span>):</span></span><br><span class="line">    newName = re.sub(<span class="string">r&#x27;\d\d\d\d-\d\d-\d\d-&#x27;</span>, <span class="string">&quot;&quot;</span>, file)</span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&quot;r&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f1,<span class="built_in">open</span>(newName, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f2:</span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> f1:</span><br><span class="line"></span><br><span class="line">            print(<span class="string">&quot;old_str&gt;&gt;&gt;&quot;</span>,old_str)</span><br><span class="line">            print(<span class="string">&quot;new_str&gt;&gt;&gt;&quot;</span>,new_str)</span><br><span class="line">            print(<span class="string">&quot;line&gt;&gt;&gt;&quot;</span>,line)</span><br><span class="line">            print(<span class="string">&quot;==================&quot;</span>)</span><br><span class="line">            f2.write(line)</span><br><span class="line">            <span class="comment"># 判断 line其那面是不是title</span></span><br><span class="line">            <span class="keyword">if</span> line[<span class="number">0</span>:<span class="number">6</span>] == <span class="string">&quot;title:&quot;</span>:</span><br><span class="line">                <span class="comment"># 说明下一行要追加 date了</span></span><br><span class="line">                f2.write(new_str)</span><br><span class="line">    os.remove(file)</span><br><span class="line">    <span class="comment"># 已经重命名了,不用这个了就</span></span><br><span class="line">    <span class="comment"># os.rename(&quot;%s.bak&quot; % file, file)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># dir 是全路径</span></span><br><span class="line"><span class="comment"># 比如: E:\Projects\PycharmProjects\untitled\test\database\redis\2019-09-25-deepin-install-redis.md</span></span><br><span class="line"><span class="comment"># :param dir:</span></span><br><span class="line"><span class="comment"># :return:</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">movDate</span>(<span class="params"><span class="built_in">dir</span></span>):</span></span><br><span class="line"></span><br><span class="line">    newDir = <span class="built_in">dir</span></span><br><span class="line">    <span class="comment"># 2. 判断是文件</span></span><br><span class="line">    <span class="keyword">if</span> os.path.isfile(<span class="built_in">dir</span>):</span><br><span class="line">        <span class="comment"># print(&quot;\t\t\t&quot; + dir + &quot;是文件&quot;)</span></span><br><span class="line">        <span class="comment"># print(&quot;&gt;&gt;&gt;&quot; + dir[-3:])</span></span><br><span class="line">        <span class="comment"># 2.1 判断是md文件</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">dir</span>[-<span class="number">3</span>:] == <span class="string">&quot;.md&quot;</span>:</span><br><span class="line">            <span class="comment"># 判断是不是日期开头的md文件,正则</span></span><br><span class="line">            <span class="comment"># print(&quot;匹配开始-----------&quot;,dir)</span></span><br><span class="line">            <span class="comment"># print(re.search(&#x27;(\d\d\d\d-\d\d-\d\d)-&#x27;, dir))</span></span><br><span class="line">            searchObj = re.search(<span class="string">&#x27;\d\d\d\d-\d\d-\d\d-&#x27;</span>, <span class="built_in">dir</span>)</span><br><span class="line">            <span class="comment"># 要是有结果</span></span><br><span class="line">            <span class="keyword">if</span> searchObj:</span><br><span class="line">                print(<span class="built_in">dir</span> + <span class="string">&quot;是日期开头的md文件&quot;</span>)</span><br><span class="line">                <span class="comment"># 暂存 日期</span></span><br><span class="line">                date_str = searchObj.group(<span class="number">0</span>)[:-<span class="number">1</span>]</span><br><span class="line">                <span class="comment">#         date:       2015-07-09</span></span><br><span class="line">                <span class="comment"># os.rename(&quot;原文件名&quot;,&quot;新文件名&quot;）</span></span><br><span class="line">                <span class="comment"># ? 如何生成新文件名???</span></span><br><span class="line">                <span class="comment"># a = re.sub(r&#x27;hello&#x27;, &#x27;i love the&#x27;, &#x27;hello world&#x27;)</span></span><br><span class="line">                <span class="comment"># newName = re.sub(r&#x27;\d\d\d\d-\d\d-\d\d-&#x27;,&quot;&quot;,dir)</span></span><br><span class="line">                <span class="comment"># os.rename(dir,newName)</span></span><br><span class="line">                app_str = <span class="string">&quot;date:       &quot;</span>+date_str+<span class="string">&quot;\n&quot;</span></span><br><span class="line">                <span class="comment"># print(&quot;日期是 &gt;&gt;&gt; &quot; + app_str)</span></span><br><span class="line">                alter(<span class="built_in">dir</span>, <span class="string">&quot;\ntitle:&quot;</span>, app_str)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 1. 判断是文件夹</span></span><br><span class="line">    <span class="keyword">elif</span> os.path.isdir(<span class="built_in">dir</span>):</span><br><span class="line">        print(<span class="built_in">dir</span> + <span class="string">&quot;是文件夹&quot;</span>)</span><br><span class="line">        <span class="comment"># 1.1 获取列表</span></span><br><span class="line">        <span class="keyword">for</span> s <span class="keyword">in</span> os.listdir(<span class="built_in">dir</span>):</span><br><span class="line">            <span class="comment"># 如果需要忽略某些文件夹，使用以下代码</span></span><br><span class="line">            <span class="comment"># if s == &quot;xxx&quot;:</span></span><br><span class="line">            <span class="comment"># continue</span></span><br><span class="line">            newDir = os.path.join(<span class="built_in">dir</span>, s)</span><br><span class="line">            <span class="comment"># 1.2 循环递归</span></span><br><span class="line">            movDate(newDir)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">movDate(<span class="string">&#x27;E:\\Projects\\PycharmProjects\\untitled\\test\\database\\mysql4&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 判断是文件夹</span></span><br><span class="line"><span class="comment"># 1.1 获取列表</span></span><br><span class="line"><span class="comment"># 1.2 循环递归</span></span><br><span class="line"><span class="comment"># 2. 判断是文件</span></span><br><span class="line"><span class="comment"># 2.1 判断是md文件</span></span><br><span class="line"><span class="comment">#    2.1.1 获取文件名</span></span><br><span class="line"><span class="comment">#    2.1.2 切割文件名得到日期</span></span><br><span class="line"><span class="comment">#    2.1.3 暂存文件名其那面的日期</span></span><br><span class="line"><span class="comment">#    2.1.4 读取文件 with方法</span></span><br><span class="line"><span class="comment">#    2.1.5 正则匹配 追加一行 文本</span></span><br><span class="line"><span class="comment">#    2.1.6 吧之前的日期放进去</span></span><br><span class="line"><span class="comment">#    2.1.7 退出</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                 神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://www.cnblogs.com/wc-chan/p/8085452.html">python 修改文件内容3种方法</a></li><li><a href="https://www.runoob.com/python/python-reg-expressions.html">Python 正则表达式</a></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>ElasticSearch安装与介绍</title>
      <link href="operation/elastic/"/>
      <url>operation/elastic/</url>
      
        <content type="html"><![CDATA[<h2 id="Elastic-Stack简介"><a href="#Elastic-Stack简介" class="headerlink" title="Elastic Stack简介"></a>Elastic Stack简介</h2><p>如果你没有听说过Elastic Stack，那你一定听说过ELK，实际上ELK是三款软件的简称，分别是Elasticsearch、 Logstash、Kibana组成，在发展的过程中，又有新成员Beats的加入，所以就形成了Elastic Stack。所以说，ELK是旧的称呼，Elastic Stack是新的名字。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922092403279.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922092403279.png" alt="image-20200922092403279"></a></p><p>全系的Elastic Stack技术栈包括：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922092505011.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922092505011.png" alt="image-20200922092505011"></a></p><h3 id="Elasticsearch"><a href="#Elasticsearch" class="headerlink" title="Elasticsearch"></a>Elasticsearch</h3><p>Elasticsearch 基于java，是个开源分布式搜索引擎，它的特点有：分布式，零配置，自动发现，索引自动分片，索引副本机制，restful风格接口，多数据源，自动搜索负载等。</p><h3 id="Logstash"><a href="#Logstash" class="headerlink" title="Logstash"></a>Logstash</h3><p>Logstash 基于java，是一个开源的用于收集,分析和存储日志的工具。</p><h3 id="Kibana"><a href="#Kibana" class="headerlink" title="Kibana"></a>Kibana</h3><p>Kibana 基于nodejs，也是一个开源和免费的工具，Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的Web 界面，可以汇总、分析和搜索重要数据日志。</p><h3 id="Beats"><a href="#Beats" class="headerlink" title="Beats"></a>Beats</h3><p>Beats是elastic公司开源的一款采集系统监控数据的代理agent，是在被监控服务器上以客户端形式运行的数据收集器的统称，可以直接把数据发送给Elasticsearch或者通过Logstash发送给Elasticsearch，然后进行后续的数据分析活动。Beats由如下组成:</p><ul><li>Packetbeat：是一个网络数据包分析器，用于监控、收集网络流量信息，Packetbeat嗅探服务器之间的流量，解析应用层协议，并关联到消息的处理，其支 持ICMP (v4 and v6)、DNS、HTTP、Mysql、PostgreSQL、Redis、MongoDB、Memcache等协议；</li><li>Filebeat：用于监控、收集服务器日志文件，其已取代 logstash forwarder；</li><li>Metricbeat：可定期获取外部系统的监控指标信息，其可以监控、收集 Apache、HAProxy、MongoDB MySQL、Nginx、PostgreSQL、Redis、System、Zookeeper等服务；</li></ul><blockquote><p>Beats和Logstash其实都可以进行数据的采集，但是目前主流的是使用Beats进行数据采集，然后使用 Logstash进行数据的分割处理等，早期没有Beats的时候，使用的就是Logstash进行数据的采集。</p></blockquote><h2 id="ElasticSearch快速入门"><a href="#ElasticSearch快速入门" class="headerlink" title="ElasticSearch快速入门"></a>ElasticSearch快速入门</h2><h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p>官网：<a href="https://www.elastic.co/">https://www.elastic.co/</a></p><p>ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎，基于RESTful web接口。Elasticsearch是用Java开发的，并作为Apache许可条款下的开放源码发布，是当前流行的企业级搜索引擎。设计用于云计算中，能够达到实时搜索，稳定，可靠，快速，安装使用方便。</p><p>我们建立一个网站或应用程序，并要添加搜索功能，但是想要完成搜索工作的创建是非常困难的。我们希望搜索解决方案要运行速度快，我们希望能有一个零配置和一个完全免费的搜索模式，我们希望能够简单地使用JSON通过HTTP来索引数据，我们希望我们的搜索服务器始终可用，我们希望能够从一台开始并扩展到数百台，我们要实时搜索，我们要简单的多租户，我们希望建立一个云的解决方案。因此我们利用Elasticsearch来解决所有这些问题及可能出现的更多其它问题。</p><p>ElasticSearch是Elastic Stack的核心，同时Elasticsearch 是一个分布式、RESTful风格的搜索和数据分析引擎，能够解决不断涌现出的各种用例。作为Elastic Stack的核心，它集中存储您的数据，帮助您发现意料之中以及意料之外的情况。</p><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>Elasticsearch的发展是非常快速的，所以在ES5.0之前，ELK的各个版本都不统一，出现了版本号混乱的状态，所以从5.0开始，所有Elastic Stack中的项目全部统一版本号。目前最新版本是6.5.4，我们将基于这一版本进行学习。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922093432839.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922093432839.png" alt="image-20200922093432839"></a></p><h3 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h3><p>到官网下载：<a href="https://www.elastic.co/cn/downloads/">https://www.elastic.co/cn/downloads/</a></p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922094003384.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922094003384.png" alt="image-20200922094003384"></a></p><p>选择对应版本的数据，这里我使用的是Linux来进行安装，所以就先下载好ElasticSearch的Linux安装包</p><h3 id="拉取Docker容器"><a href="#拉取Docker容器" class="headerlink" title="拉取Docker容器"></a>拉取Docker容器</h3><p>因为我们需要部署在Linux下，为了以后迁移ElasticStack环境方便，我们就使用Docker来进行部署，首先我们拉取一个带有ssh的centos docker镜像</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 拉取镜像</span></span><br><span class="line">docker pull moxi/centos_ssh</span><br><span class="line"><span class="comment"># 制作容器</span></span><br><span class="line">docker run --privileged -d -it -h ElasticStack --name ElasticStack -p 11122:22 -p 9200:9200 -p 5601:5601 -p 9300:9300 -v /etc/localtime:/etc/localtime:ro  moxi/centos_ssh /usr/sbin/init</span><br></pre></td></tr></table></figure><p>然后直接远程连接11122端口即可</p><h3 id="单机版安装"><a href="#单机版安装" class="headerlink" title="单机版安装"></a>单机版安装</h3><p>因为ElasticSearch不支持Root用户直接操作，因此我们需要创建一个elsearch用户</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 添加新用户</span></span><br><span class="line">useradd elsearch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建一个soft目录，存放下载的软件</span></span><br><span class="line">mkdir /soft</span><br><span class="line"></span><br><span class="line"><span class="comment"># 进入，然后通过xftp工具，将刚刚下载的文件拖动到该目录下</span></span><br><span class="line"><span class="built_in">cd</span> /soft</span><br><span class="line"></span><br><span class="line"><span class="comment"># 解压缩</span></span><br><span class="line">tar -zxvf elasticsearch-7.9.1-linux-x86_64.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="comment">#重命名</span></span><br><span class="line">mv elasticsearch-7.9.1/ elsearch</span><br></pre></td></tr></table></figure><p>因为刚刚我们是使用root用户操作的，所以我们还需要更改一下/soft文件夹的所属，改为elsearch用户</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chown elsearch:elsearch /soft/ -R</span><br></pre></td></tr></table></figure><p>然后在切换成elsearch用户进行操作</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 切换用户</span></span><br><span class="line">su - elsearch</span><br></pre></td></tr></table></figure><p>然后我们就可以对我们的配置文件进行修改了</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 进入到 elsearch下的config目录</span></span><br><span class="line"><span class="built_in">cd</span> /soft/elsearch/config</span><br></pre></td></tr></table></figure><p>然后找到下面的配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#打开配置文件</span></span><br><span class="line"><span class="string">vim</span> <span class="string">elasticsearch.yml</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">#设置ip地址，任意网络均可访问</span></span><br><span class="line"><span class="attr">network.host:</span> <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span></span><br></pre></td></tr></table></figure><p>在Elasticsearch中如果，network.host不是localhost或者127.0.0.1的话，就会认为是生产环境，会对环境的要求比较高，我们的测试环境不一定能够满足，一般情况下需要修改2处配置，如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 修改jvm启动参数</span></span><br><span class="line">vim conf/jvm.options</span><br><span class="line"></span><br><span class="line"><span class="comment">#根据自己机器情况修改</span></span><br><span class="line">-Xms128m </span><br><span class="line">-Xmx128m</span><br></pre></td></tr></table></figure><p>然后在修改第二处的配置，这个配置要求我们到宿主机器上来进行配置</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 到宿主机上打开文件</span></span><br><span class="line">vim /etc/sysctl.conf</span><br><span class="line"><span class="comment"># 增加这样一条配置，一个进程在VMAs(虚拟内存区域)创建内存映射最大数量</span></span><br><span class="line">vm.max_map_count=655360</span><br><span class="line"><span class="comment"># 让配置生效</span></span><br><span class="line">sysctl -p</span><br></pre></td></tr></table></figure><h3 id="启动ElasticSearch"><a href="#启动ElasticSearch" class="headerlink" title="启动ElasticSearch"></a>启动ElasticSearch</h3><p>首先我们需要切换到 elsearch用户</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">su - elsearch</span><br></pre></td></tr></table></figure><p>然后在到bin目录下，执行下面</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 进入bin目录</span></span><br><span class="line"><span class="built_in">cd</span> /soft/elsearch/bin</span><br><span class="line"><span class="comment"># 后台启动</span></span><br><span class="line">./elasticsearch -d</span><br></pre></td></tr></table></figure><p>启动成功后，访问下面的URL</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://202.193.56.222:9200/</span><br></pre></td></tr></table></figure><p>如果出现了下面的信息，就表示已经成功启动了</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922150758205.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922150758205.png" alt="image-20200922150758205"></a></p><p>如果你在启动的时候，遇到过问题，那么请参考下面的错误分析~</p><h2 id="错误分析"><a href="#错误分析" class="headerlink" title="错误分析"></a>错误分析</h2><h3 id="错误情况1"><a href="#错误情况1" class="headerlink" title="错误情况1"></a>错误情况1</h3><p>如果出现下面的错误信息</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">java.lang.RuntimeException: can not run elasticsearch as root</span><br><span class="line">    at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:111)</span><br><span class="line">    at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:178)</span><br><span class="line">    at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:393)</span><br><span class="line">    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170)</span><br><span class="line">    at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:161)</span><br><span class="line">    at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86)</span><br><span class="line">    at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:127)</span><br><span class="line">    at org.elasticsearch.cli.Command.main(Command.java:90)</span><br><span class="line">    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:126)</span><br><span class="line">    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92)</span><br><span class="line">For complete error details, refer to the log at &#x2F;soft&#x2F;elsearch&#x2F;logs&#x2F;elasticsearch.log</span><br><span class="line">[root@e588039bc613 bin]# 2020-09-22 02:59:39,537121 UTC [536] ERROR CLogger.cc@310 Cannot log to named pipe &#x2F;tmp&#x2F;elasticsearch-5834501324803693929&#x2F;controller_log_381 as it could not be opened for writing</span><br><span class="line">2020-09-22 02:59:39,537263 UTC [536] INFO  Main.cc@103 Parent process died - ML controller exiting</span><br></pre></td></tr></table></figure><p>就说明你没有切换成 elsearch用户，因为不能使用root操作es</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">su - elsearch</span><br></pre></td></tr></table></figure><h3 id="错误情况2"><a href="#错误情况2" class="headerlink" title="错误情况2"></a>错误情况2</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[1]:max file descriptors [4096] <span class="keyword">for</span> elasticsearch process is too low, increase to at least[65536]</span><br></pre></td></tr></table></figure><p>解决方法：切换到root用户，编辑limits.conf添加如下内容</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">vi /etc/security/limits.conf</span><br><span class="line"></span><br><span class="line"><span class="comment"># ElasticSearch添加如下内容:</span></span><br><span class="line">* soft nofile 65536</span><br><span class="line">* hard nofile 131072</span><br><span class="line">* soft nproc 2048</span><br><span class="line">* hard nproc 4096</span><br></pre></td></tr></table></figure><h3 id="错误情况3"><a href="#错误情况3" class="headerlink" title="错误情况3"></a>错误情况3</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[2]: max number of threads [1024] <span class="keyword">for</span> user [elsearch] is too low, increase to at least</span><br><span class="line">[4096]</span><br></pre></td></tr></table></figure><p>也就是最大线程数设置的太低了，需要改成4096</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#解决：切换到root用户，进入limits.d目录下修改配置文件。</span></span><br><span class="line">vi /etc/security/limits.d/90-nproc.conf</span><br><span class="line"><span class="comment">#修改如下内容：</span></span><br><span class="line">* soft nproc 1024</span><br><span class="line"><span class="comment">#修改为</span></span><br><span class="line">* soft nproc 4096</span><br></pre></td></tr></table></figure><h3 id="错误情况4"><a href="#错误情况4" class="headerlink" title="错误情况4"></a>错误情况4</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[3]: system call filters failed to install; check the logs and fix your configuration</span><br><span class="line">or <span class="built_in">disable</span> system call filters at your own risk</span><br></pre></td></tr></table></figure><p>解决：Centos6不支持SecComp，而ES5.2.0默认bootstrap.system_call_filter为true</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">vim config/elasticsearch.yml</span><br><span class="line"><span class="comment"># 添加</span></span><br><span class="line">bootstrap.system_call_filter: <span class="literal">false</span></span><br><span class="line">bootstrap.memory_lock: <span class="literal">false</span></span><br></pre></td></tr></table></figure><h3 id="错误情况5"><a href="#错误情况5" class="headerlink" title="错误情况5"></a>错误情况5</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">[elsearch@e588039bc613 bin]$ Exception <span class="keyword">in</span> thread <span class="string">&quot;main&quot;</span> org.elasticsearch.bootstrap.BootstrapException: java.nio.file.AccessDeniedException: /soft/elsearch/config/elasticsearch.keystore</span><br><span class="line">Likely root cause: java.nio.file.AccessDeniedException: /soft/elsearch/config/elasticsearch.keystore</span><br><span class="line">    at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)</span><br><span class="line">    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)</span><br><span class="line">    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)</span><br><span class="line">    at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:219)</span><br><span class="line">    at java.base/java.nio.file.Files.newByteChannel(Files.java:375)</span><br><span class="line">    at java.base/java.nio.file.Files.newByteChannel(Files.java:426)</span><br><span class="line">    at org.apache.lucene.store.SimpleFSDirectory.openInput(SimpleFSDirectory.java:79)</span><br><span class="line">    at org.elasticsearch.common.settings.KeyStoreWrapper.load(KeyStoreWrapper.java:220)</span><br><span class="line">    at org.elasticsearch.bootstrap.Bootstrap.loadSecureSettings(Bootstrap.java:240)</span><br><span class="line">    at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:349)</span><br><span class="line">    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170)</span><br><span class="line">    at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:161)</span><br><span class="line">    at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86)</span><br><span class="line">    at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:127)</span><br><span class="line">    at org.elasticsearch.cli.Command.main(Command.java:90)</span><br><span class="line">    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:126)</span><br><span class="line">    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92)</span><br></pre></td></tr></table></figure><p>我们通过排查，发现是因为 /soft/elsearch/config/elasticsearch.keystore 存在问题</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922111823740.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922111823740.png" alt="image-20200922111823740"></a></p><p>也就是说该文件还是所属于root用户，而我们使用elsearch用户无法操作，所以需要把它变成elsearch</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chown elsearch:elsearch elasticsearch.keystore</span><br></pre></td></tr></table></figure><h3 id="错误情况6"><a href="#错误情况6" class="headerlink" title="错误情况6"></a>错误情况6</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[1]: the default discovery settings are unsuitable <span class="keyword">for</span> production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured</span><br><span class="line">ERROR: Elasticsearch did not <span class="built_in">exit</span> normally - check the logs at /soft/elsearch/logs/elasticsearch.log</span><br></pre></td></tr></table></figure><p>继续修改配置 elasticsearch.yaml</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 取消注释，并保留一个节点</span></span><br><span class="line">node.name: node-1</span><br><span class="line">cluster.initial_master_nodes: [<span class="string">&quot;node-1&quot;</span>]</span><br></pre></td></tr></table></figure><h2 id="ElasticSearchHead可视化工具"><a href="#ElasticSearchHead可视化工具" class="headerlink" title="ElasticSearchHead可视化工具"></a>ElasticSearchHead可视化工具</h2><p>由于ES官方没有给ES提供可视化管理工具，仅仅是提供了后台的服务，elasticsearch-head是一个为ES开发的一个页面客户端工具，其源码托管于Github，地址为 <a href="https://github.com/mobz/elasticsearch-head">传送门</a></p><p>head提供了以下安装方式</p><ul><li>源码安装，通过npm run start启动（不推荐）</li><li>通过docker安装（推荐）</li><li>通过chrome插件安装（推荐）</li><li>通过ES的plugin方式安装（不推荐）</li></ul><h3 id="通过Docker方式安装"><a href="#通过Docker方式安装" class="headerlink" title="通过Docker方式安装"></a>通过Docker方式安装</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#拉取镜像</span></span><br><span class="line">docker pull mobz/elasticsearch-head:5</span><br><span class="line"><span class="comment">#创建容器</span></span><br><span class="line">docker create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5</span><br><span class="line"><span class="comment">#启动容器</span></span><br><span class="line">docker start elasticsearch-head</span><br></pre></td></tr></table></figure><p>通过浏览器进行访问：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922151529269.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922151529269.png" alt="image-20200922151529269"></a></p><p>注意： 由于前后端分离开发，所以会存在跨域问题，需要在服务端做CORS的配置，如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">vim elasticsearch.yml</span><br><span class="line"></span><br><span class="line">http.cors.enabled: <span class="literal">true</span> http.cors.allow-origin: <span class="string">&quot;*&quot;</span></span><br></pre></td></tr></table></figure><p>通过chrome插件的方式安装不存在该问题</p><h3 id="通过Chrome插件安装"><a href="#通过Chrome插件安装" class="headerlink" title="通过Chrome插件安装"></a>通过Chrome插件安装</h3><p>打开chrome的应用商店，即可安装 <a href="https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm">https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm</a></p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922152428838.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922152428838.png" alt="image-20200922152428838"></a></p><p>我们也可以新建索引</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922152534471.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922152534471.png" alt="image-20200922152534471"></a></p><p>建议：推荐使用chrome插件的方式安装，如果网络环境不允许，就采用其它方式安装。</p><h2 id="ElasticSearch中的基本概念"><a href="#ElasticSearch中的基本概念" class="headerlink" title="ElasticSearch中的基本概念"></a>ElasticSearch中的基本概念</h2><h3 id="索引"><a href="#索引" class="headerlink" title="索引"></a>索引</h3><ul><li>索引（index）是Elasticsearch对逻辑数据的逻辑存储，所以它可以分为更小的部分。</li><li>可以把索引看成关系型数据库的表，索引的结构是为快速有效的全文索引准备的，特别是它不存储原始值。</li><li>Elasticsearch可以把索引存放在一台机器或者分散在多台服务器上，每个索引有一或多个分片（shard），每个分片可以有多个副本（replica）。</li></ul><h3 id="文档"><a href="#文档" class="headerlink" title="文档"></a>文档</h3><ul><li>存储在Elasticsearch中的主要实体叫文档（document）。用关系型数据库来类比的话，一个文档相当于数据库表中的一行记录。</li><li>Elasticsearch和MongoDB中的文档类似，都可以有不同的结构，但Elasticsearch的文档中，相同字段必须有相同类型。</li><li>文档由多个字段组成，每个字段可能多次出现在一个文档里，这样的字段叫多值字段（multivalued）。 每个字段的类型，可以是文本、数值、日期等。字段类型也可以是复杂类型，一个字段包含其他子文档或者数 组。</li></ul><h3 id="映射"><a href="#映射" class="headerlink" title="映射"></a>映射</h3><p>所有文档写进索引之前都会先进行分析，如何将输入的文本分割为词条、哪些词条又会被过滤，这种行为叫做 映射（mapping）。一般由用户自己定义规则。</p><h3 id="文档类型"><a href="#文档类型" class="headerlink" title="文档类型"></a>文档类型</h3><ul><li>在Elasticsearch中，一个索引对象可以存储很多不同用途的对象。例如，一个博客应用程序可以保存文章和评 论。</li><li>每个文档可以有不同的结构。</li><li>不同的文档类型不能为相同的属性设置不同的类型。例如，在同一索引中的所有文档类型中，一个叫title的字段必须具有相同的类型。</li></ul><h2 id="RESTful-API"><a href="#RESTful-API" class="headerlink" title="RESTful API"></a>RESTful API</h2><p>在Elasticsearch中，提供了功能丰富的RESTful API的操作，包括基本的CRUD、创建索引、删除索引等操作。</p><h3 id="创建非结构化索引"><a href="#创建非结构化索引" class="headerlink" title="创建非结构化索引"></a>创建非结构化索引</h3><p>在Lucene中，创建索引是需要定义字段名称以及字段的类型的，在Elasticsearch中提供了非结构化的索引，就是不需要创建索引结构，即可写入数据到索引中，实际上在Elasticsearch底层会进行结构化操作，此操作对用户是透明的。</p><h3 id="创建空索引"><a href="#创建空索引" class="headerlink" title="创建空索引"></a>创建空索引</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">PUT /haoke</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;settings&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;index&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;number_of_shards&quot;</span>: <span class="string">&quot;2&quot;</span>, <span class="comment">#分片数</span></span><br><span class="line">        <span class="string">&quot;number_of_replicas&quot;</span>: <span class="string">&quot;0&quot;</span> <span class="comment">#副本数</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="删除索引"><a href="#删除索引" class="headerlink" title="删除索引"></a>删除索引</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#删除索引</span></span><br><span class="line">DELETE /haoke</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;acknowledged&quot;</span>: <span class="literal">true</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="插入数据"><a href="#插入数据" class="headerlink" title="插入数据"></a>插入数据</h3><blockquote><p>URL规则： POST /{索引}/{类型}/{id}</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/1001</span><br><span class="line"><span class="comment">#数据</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="string">&quot;id&quot;</span>:1001,</span><br><span class="line"><span class="string">&quot;name&quot;</span>:<span class="string">&quot;张三&quot;</span>,</span><br><span class="line"><span class="string">&quot;age&quot;</span>:20,</span><br><span class="line"><span class="string">&quot;sex&quot;</span>:<span class="string">&quot;男&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>使用postman操作成功后</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922155642306.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922155642306.png" alt="image-20200922155642306"></a></p><p>我们通过ElasticSearchHead进行数据预览就能够看到我们刚刚插入的数据了</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922155843314.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922155843314.png" alt="image-20200922155843314"></a></p><p>说明：非结构化的索引，不需要事先创建，直接插入数据默认创建索引。不指定id插入数据：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922155935366.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922155935366.png" alt="image-20200922155935366"></a></p><h3 id="更新数据"><a href="#更新数据" class="headerlink" title="更新数据"></a>更新数据</h3><p>在Elasticsearch中，文档数据是不为修改的，但是可以通过覆盖的方式进行更新。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">PUT /haoke/user/1001</span><br><span class="line">&#123;</span><br><span class="line"><span class="string">&quot;id&quot;</span>:1001,</span><br><span class="line"><span class="string">&quot;name&quot;</span>:<span class="string">&quot;张三&quot;</span>,</span><br><span class="line"><span class="string">&quot;age&quot;</span>:21,</span><br><span class="line"><span class="string">&quot;sex&quot;</span>:<span class="string">&quot;女&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>更新结果如下：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160154599.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160154599.png" alt="image-20200922160154599"></a></p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160201130.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160201130.png" alt="image-20200922160201130"></a></p><p>可以看到数据已经被覆盖了。问题来了，可以局部更新吗？ – 可以的。前面不是说，文档数据不能更新吗？ 其实是这样的：在内部，依然会查询到这个文档数据，然后进行覆盖操作，步骤如下：</p><ol><li>从旧文档中检索JSON</li><li>修改它</li><li>删除旧文档</li><li>索引新文档</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#注意：这里多了_update标识</span></span><br><span class="line">POST /haoke/user/1001/_update</span><br><span class="line">&#123;</span><br><span class="line"><span class="string">&quot;doc&quot;</span>:&#123;</span><br><span class="line"><span class="string">&quot;age&quot;</span>:23</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160709463.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160709463.png" alt="image-20200922160709463"></a></p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160717001.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160717001.png" alt="image-20200922160717001"></a></p><p>可以看到，数据已经是局部更新了</p><h3 id="删除索引-1"><a href="#删除索引-1" class="headerlink" title="删除索引"></a>删除索引</h3><p>在Elasticsearch中，删除文档数据，只需要发起DELETE请求即可，不用额外的参数</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DELETE 1 /haoke/user/1001</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160752862.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922160752862.png" alt="image-20200922160752862"></a></p><p>需要注意的是，result表示已经删除，version也增加了。</p><p>如果删除一条不存在的数据，会响应404</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922161627716.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922161627716.png" alt="image-20200922161627716"></a></p><blockquote><p>删除一个文档也不会立即从磁盘上移除，它只是被标记成已删除。Elasticsearch将会在你之后添加更多索引的时候才会在后台进行删除内容的清理。【相当于批量操作】</p></blockquote><h3 id="搜索数据"><a href="#搜索数据" class="headerlink" title="搜索数据"></a>搜索数据</h3><h4 id="根据id搜索数据"><a href="#根据id搜索数据" class="headerlink" title="根据id搜索数据"></a>根据id搜索数据</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">GET /haoke/user/BbPe_WcB9cFOnF3uebvr</span><br><span class="line"><span class="comment">#返回的数据如下</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;_index&quot;</span>: <span class="string">&quot;haoke&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_type&quot;</span>: <span class="string">&quot;user&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_id&quot;</span>: <span class="string">&quot;BbPe_WcB9cFOnF3uebvr&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_version&quot;</span>: 8,</span><br><span class="line">    <span class="string">&quot;found&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;_source&quot;</span>: &#123; <span class="comment">#原始数据在这里</span></span><br><span class="line">        <span class="string">&quot;id&quot;</span>: 1002,</span><br><span class="line">        <span class="string">&quot;name&quot;</span>: <span class="string">&quot;李四&quot;</span>,</span><br><span class="line">        <span class="string">&quot;age&quot;</span>: 40,</span><br><span class="line">        <span class="string">&quot;sex&quot;</span>: <span class="string">&quot;男&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="搜索全部数据"><a href="#搜索全部数据" class="headerlink" title="搜索全部数据"></a>搜索全部数据</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET 1 /haoke/user/_search</span><br></pre></td></tr></table></figure><p>注意，使用查询全部数据的时候，默认只会返回10条</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922162228822.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922162228822.png" alt="image-20200922162228822"></a></p><h4 id="关键字搜索数据"><a href="#关键字搜索数据" class="headerlink" title="关键字搜索数据"></a>关键字搜索数据</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#查询年龄等于20的用户</span></span><br><span class="line">GET /haoke/user/_search?q=age:20</span><br></pre></td></tr></table></figure><p>结果如下：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922162309797.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922162309797.png" alt="image-20200922162309797"></a></p><h3 id="DSL搜索"><a href="#DSL搜索" class="headerlink" title="DSL搜索"></a>DSL搜索</h3><p>Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。 DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/_search</span><br><span class="line"><span class="comment">#请求体</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span> : &#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span> : &#123; <span class="comment">#match只是查询的一种</span></span><br><span class="line">            <span class="string">&quot;age&quot;</span> : 20</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>实现：查询年龄大于30岁的男性用户。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922162943539.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922162943539.png" alt="image-20200922162943539"></a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/_search</span><br><span class="line"><span class="comment">#请求数据</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;bool&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;filter&quot;</span>: &#123;</span><br><span class="line">                    <span class="string">&quot;range&quot;</span>: &#123;</span><br><span class="line">                        <span class="string">&quot;age&quot;</span>: &#123;</span><br><span class="line">                        <span class="string">&quot;gt&quot;</span>: 30</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">&quot;must&quot;</span>: &#123;</span><br><span class="line">                <span class="string">&quot;match&quot;</span>: &#123;</span><br><span class="line">                    <span class="string">&quot;sex&quot;</span>: <span class="string">&quot;男&quot;</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>查询出来的结果</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922163109515.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922163109515.png" alt="image-20200922163109515"></a></p><h4 id="全文搜索"><a href="#全文搜索" class="headerlink" title="全文搜索"></a>全文搜索</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/_search</span><br><span class="line"><span class="comment">#请求数据</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;name&quot;</span>: <span class="string">&quot;张三 李四&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922163315285.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922163315285.png" alt="image-20200922163315285"></a></p><p>高亮显示，只需要在添加一个 highlight即可</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/_search</span><br><span class="line"><span class="comment">#请求数据</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;name&quot;</span>: <span class="string">&quot;张三 李四&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="string">&quot;highlight&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;fields&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;name&quot;</span>: &#123;&#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922163432853.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922163432853.png" alt="image-20200922163432853"></a></p><h4 id="聚合"><a href="#聚合" class="headerlink" title="聚合"></a>聚合</h4><p>在Elasticsearch中，支持聚合操作，类似SQL中的group by操作。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;aggs&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;all_interests&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;terms&quot;</span>: &#123;</span><br><span class="line">                <span class="string">&quot;field&quot;</span>: <span class="string">&quot;age&quot;</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>结果如下，我们通过年龄进行聚合</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922163614708.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922163614708.png" alt="image-20200922163614708"></a></p><p>从结果可以看出，年龄30的有2条数据，20的有一条，40的一条。</p><h2 id="ElasticSearch核心详解"><a href="#ElasticSearch核心详解" class="headerlink" title="ElasticSearch核心详解"></a>ElasticSearch核心详解</h2><h3 id="文档-1"><a href="#文档-1" class="headerlink" title="文档"></a>文档</h3><p>在Elasticsearch中，文档以JSON格式进行存储，可以是复杂的结构，如：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;_index&quot;</span>: <span class="string">&quot;haoke&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_type&quot;</span>: <span class="string">&quot;user&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_id&quot;</span>: <span class="string">&quot;1005&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_version&quot;</span>: 1,</span><br><span class="line">    <span class="string">&quot;_score&quot;</span>: 1,</span><br><span class="line">    <span class="string">&quot;_source&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;id&quot;</span>: 1005,</span><br><span class="line">        <span class="string">&quot;name&quot;</span>: <span class="string">&quot;孙七&quot;</span>,</span><br><span class="line">        <span class="string">&quot;age&quot;</span>: 37,</span><br><span class="line">        <span class="string">&quot;sex&quot;</span>: <span class="string">&quot;女&quot;</span>,</span><br><span class="line">        <span class="string">&quot;card&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;card_number&quot;</span>: <span class="string">&quot;123456789&quot;</span></span><br><span class="line">         &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中，card是一个复杂对象，嵌套的Card对象</p><h4 id="元数据（metadata）"><a href="#元数据（metadata）" class="headerlink" title="元数据（metadata）"></a>元数据（metadata）</h4><p>一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。三个必须的元数据节点是：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922165956176.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200922165956176.png" alt="image-20200922165956176"></a></p><h4 id="index"><a href="#index" class="headerlink" title="index"></a>index</h4><p>索引(index)类似于关系型数据库里的“数据库”——它是我们存储和索引关联数据的地方。</p><blockquote><p>提示：事实上，我们的数据被存储和索引在分片(shards)中，索引只是一个把一个或多个分片分组在一起的逻辑空间。然而，这只是一些内部细节——我们的程序完全不用关心分片。对于我们的程序而言，文档存储在索引(index)中。剩下的细节由Elasticsearch关心既可。</p></blockquote><h4 id="type"><a href="#type" class="headerlink" title="_type"></a>_type</h4><p>在应用中，我们使用对象表示一些“事物”，例如一个用户、一篇博客、一个评论，或者一封邮件。每个对象都属于一个类(class)，这个类定义了属性或与对象关联的数据。user 类的对象可能包含姓名、性别、年龄和Email地址。 在关系型数据库中，我们经常将相同类的对象存储在一个表里，因为它们有着相同的结构。同理，在Elasticsearch 中，我们使用相同类型(type)的文档表示相同的“事物”，因为他们的数据结构也是相同的。</p><p>每个类型(type)都有自己的映射(mapping)或者结构定义，就像传统数据库表中的列一样。所有类型下的文档被存储在同一个索引下，但是类型的映射(mapping)会告诉Elasticsearch不同的文档如何被索引。</p><p>_type 的名字可以是大写或小写，不能包含下划线或逗号。我们将使用blog 做为类型名。</p><h4 id="id"><a href="#id" class="headerlink" title="_id"></a>_id</h4><p>id仅仅是一个字符串，它与_index 和_type 组合时，就可以在Elasticsearch中唯一标识一个文档。当创建一个文 档，你可以自定义_id ，也可以让Elasticsearch帮你自动生成（32位长度）</p><h3 id="查询响应"><a href="#查询响应" class="headerlink" title="查询响应"></a>查询响应</h3><h4 id="pretty"><a href="#pretty" class="headerlink" title="pretty"></a>pretty</h4><p>可以在查询url后面添加pretty参数，使得返回的json更易查看。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101056932.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101056932.png" alt="image-20200923101056932"></a></p><h4 id="指定响应字段"><a href="#指定响应字段" class="headerlink" title="指定响应字段"></a>指定响应字段</h4><p>在响应的数据中，如果我们不需要全部的字段，可以指定某些需要的字段进行返回。通过添加 _source</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">GET /haoke/user/1005?_source=id,name</span><br><span class="line"><span class="comment">#响应</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;_index&quot;</span>: <span class="string">&quot;haoke&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_type&quot;</span>: <span class="string">&quot;user&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_id&quot;</span>: <span class="string">&quot;1005&quot;</span>,</span><br><span class="line">    <span class="string">&quot;_version&quot;</span>: 1,</span><br><span class="line">    <span class="string">&quot;found&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;_source&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;name&quot;</span>: <span class="string">&quot;孙七&quot;</span>,</span><br><span class="line">        <span class="string">&quot;id&quot;</span>: 1005</span><br><span class="line">     &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如不需要返回元数据，仅仅返回原始数据，可以这样：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /haoke/1 user/1005/_source</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101239226.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101239226.png" alt="image-20200923101239226"></a></p><p>还可以这样：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /haoke/user/1005/_source?_1 <span class="built_in">source</span>=id,name</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101319728.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101319728.png" alt="image-20200923101319728"></a></p><h4 id="判断文档是否存在"><a href="#判断文档是否存在" class="headerlink" title="判断文档是否存在"></a>判断文档是否存在</h4><p>如果我们只需要判断文档是否存在，而不是查询文档内容，那么可以这样：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HEAD /haoke/user/1005</span><br></pre></td></tr></table></figure><p>通过发送一个head请求，来判断数据是否存在</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101354992.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101354992.png" alt="image-20200923101354992"></a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HEAD 1 /haoke/user/1006</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101433608.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101433608.png" alt="image-20200923101433608"></a></p><blockquote><p>当然，这只表示你在查询的那一刻文档不存在，但并不表示几毫秒后依旧不存在。另一个进程在这期间可能创建新文档。</p></blockquote><h3 id="批量操作"><a href="#批量操作" class="headerlink" title="批量操作"></a>批量操作</h3><p>有些情况下可以通过批量操作以减少网络请求。如：批量查询、批量插入数据。</p><h4 id="批量查询"><a href="#批量查询" class="headerlink" title="批量查询"></a>批量查询</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/_mget</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;ids&quot;</span> : [ <span class="string">&quot;1001&quot;</span>, <span class="string">&quot;1003&quot;</span> ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>结果：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101540616.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101540616.png" alt="image-20200923101540616"></a></p><p>如果，某一条数据不存在，不影响整体响应，需要通过found的值进行判断是否查询到数据。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/_mget</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;ids&quot;</span> : [ <span class="string">&quot;1001&quot;</span>, <span class="string">&quot;1006&quot;</span> ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>结果：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101721344.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101721344.png" alt="image-20200923101721344"></a></p><blockquote><p>也就是说，一个数据的存在不会影响其它数据的返回</p></blockquote><h4 id="bulk操作"><a href="#bulk操作" class="headerlink" title="_bulk操作"></a>_bulk操作</h4><p>在Elasticsearch中，支持批量的插入、修改、删除操作，都是通过_bulk的api完成的。</p><p>请求格式如下：（请求格式不同寻常）</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123; action: &#123; metadata &#125;&#125;</span><br><span class="line">&#123; request body &#125;</span><br><span class="line">&#123; action: &#123; metadata &#125;&#125;</span><br><span class="line">&#123; request body &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>批量插入数据：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="string">&quot;create&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;user&quot;</span>,<span class="string">&quot;_id&quot;</span>:2001&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:2001,<span class="string">&quot;name&quot;</span>:<span class="string">&quot;name1&quot;</span>,<span class="string">&quot;age&quot;</span>: 20,<span class="string">&quot;sex&quot;</span>: <span class="string">&quot;男&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;create&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;user&quot;</span>,<span class="string">&quot;_id&quot;</span>:2002&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:2002,<span class="string">&quot;name&quot;</span>:<span class="string">&quot;name2&quot;</span>,<span class="string">&quot;age&quot;</span>: 20,<span class="string">&quot;sex&quot;</span>: <span class="string">&quot;男&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;create&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;user&quot;</span>,<span class="string">&quot;_id&quot;</span>:2003&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:2003,<span class="string">&quot;name&quot;</span>:<span class="string">&quot;name3&quot;</span>,<span class="string">&quot;age&quot;</span>: 20,<span class="string">&quot;sex&quot;</span>: <span class="string">&quot;男&quot;</span>&#125;</span><br></pre></td></tr></table></figure><p>注意最后一行的回车。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101946147.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923101946147.png" alt="image-20200923101946147"></a></p><p>批量删除：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="string">&quot;delete&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;user&quot;</span>,<span class="string">&quot;_id&quot;</span>:2001&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;delete&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;user&quot;</span>,<span class="string">&quot;_id&quot;</span>:2002&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;delete&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;user&quot;</span>,<span class="string">&quot;_id&quot;</span>:2003&#125;&#125;</span><br></pre></td></tr></table></figure><p>由于delete没有请求体，所以，action的下一行直接就是下一个action。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923102044231.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923102044231.png" alt="image-20200923102044231"></a></p><p>其他操作就类似了。一次请求多少性能最高？</p><ul><li>整个批量请求需要被加载到接受我们请求节点的内存里，所以请求越大，给其它请求可用的内存就越小。有一 个最佳的bulk请求大小。超过这个大小，性能不再提升而且可能降低。</li><li>最佳大小，当然并不是一个固定的数字。它完全取决于你的硬件、你文档的大小和复杂度以及索引和搜索的负 载。</li><li>幸运的是，这个最佳点(sweetspot)还是容易找到的：试着批量索引标准的文档，随着大小的增长，当性能开始 降低，说明你每个批次的大小太大了。开始的数量可以在1000~5000个文档之间，如果你的文档非常大，可以使用较小的批次。</li><li>通常着眼于你请求批次的物理大小是非常有用的。一千个1kB的文档和一千个1MB的文档大不相同。一个好的 批次最好保持在5-15MB大小间。</li></ul><h3 id="分页"><a href="#分页" class="headerlink" title="分页"></a>分页</h3><p>和SQL使用LIMIT 关键字返回只有一页的结果一样，Elasticsearch接受from 和size 参数：</p><ul><li>size: 结果数，默认10</li><li>from: 跳过开始的结果数，默认0</li></ul><p>如果你想每页显示5个结果，页码从1到3，那请求如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">GET /_search?size=5</span><br><span class="line">GET /_search?size=5&amp;from=5</span><br><span class="line">GET /_search?size=5&amp;from=10</span><br></pre></td></tr></table></figure><p>应该当心分页太深或者一次请求太多的结果。结果在返回前会被排序。但是记住一个搜索请求常常涉及多个分 片。每个分片生成自己排好序的结果，它们接着需要集中起来排序以确保整体排序正确。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /haoke/user/_1 search?size=1&amp;from=2</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923102611567.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923102611567.png" alt="image-20200923102611567"></a></p><h4 id="在集群系统中深度分页"><a href="#在集群系统中深度分页" class="headerlink" title="在集群系统中深度分页"></a>在集群系统中深度分页</h4><p>为了理解为什么深度分页是有问题的，让我们假设在一个有5个主分片的索引中搜索。当我们请求结果的第一 页（结果1到10）时，每个分片产生自己最顶端10个结果然后返回它们给请求节点(requesting node)，它再 排序这所有的50个结果以选出顶端的10个结果。</p><p>现在假设我们请求第1000页——结果10001到10010。工作方式都相同，不同的是每个分片都必须产生顶端的 10010个结果。然后请求节点排序这50050个结果并丢弃50040个！</p><p>你可以看到在分布式系统中，排序结果的花费随着分页的深入而成倍增长。这也是为什么网络搜索引擎中任何 语句不能返回多于1000个结果的原因。</p><h3 id="映射-1"><a href="#映射-1" class="headerlink" title="映射"></a>映射</h3><p>前面我们创建的索引以及插入数据，都是由Elasticsearch进行自动判断类型，有些时候我们是需要进行明确字段类型的，否则，自动判断的类型和实际需求是不相符的。</p><p>自动判断的规则如下：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923103848097.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923103848097.png" alt="image-20200923103848097"></a></p><p>Elasticsearch中支持的类型如下：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923103917807.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923103917807.png" alt="image-20200923103917807"></a></p><ul><li>string类型在ElasticSearch 旧版本中使用较多，从ElasticSearch 5.x开始不再支持string，由text和 keyword类型替代。</li><li>text 类型，当一个字段是要被全文搜索的，比如Email内容、产品描述，应该使用text类型。设置text类型 以后，字段内容会被分析，在生成倒排索引以前，字符串会被分析器分成一个一个词项。text类型的字段 不用于排序，很少用于聚合。</li><li>keyword类型适用于索引结构化的字段，比如email地址、主机名、状态码和标签。如果字段需要进行过 滤(比如查找已发布博客中status属性为published的文章)、排序、聚合。keyword类型的字段只能通过精 确值搜索到。</li></ul><h4 id="创建明确类型的索引："><a href="#创建明确类型的索引：" class="headerlink" title="创建明确类型的索引："></a>创建明确类型的索引：</h4><blockquote><p>如果你要像之前旧版版本一样兼容自定义 type ,需要将 <strong>i</strong>nclude_type_name=true 携带</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">put http://202.193.56.222:9200/itcast?include_type_name=<span class="literal">true</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;settings&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;index&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;number_of_shards&quot;</span>:<span class="string">&quot;2&quot;</span>,</span><br><span class="line">            <span class="string">&quot;number_of_replicas&quot;</span>:<span class="string">&quot;0&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;mappings&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;person&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;properties&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;name&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;type&quot;</span>:<span class="string">&quot;text&quot;</span></span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="string">&quot;age&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;type&quot;</span>:<span class="string">&quot;integer&quot;</span></span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="string">&quot;mail&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;type&quot;</span>:<span class="string">&quot;keyword&quot;</span></span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;type&quot;</span>:<span class="string">&quot;text&quot;</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>查看映射</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /itcast/_mapping</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923104201613.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923104201613.png" alt="image-20200923104201613"></a></p><p>插入数据</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/_bulk</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;张三&quot;</span>,<span class="string">&quot;age&quot;</span>: 20,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;111@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;羽毛球、乒乓球、足球&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;李四&quot;</span>,<span class="string">&quot;age&quot;</span>: 21,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;222@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;羽毛球、乒乓球、足球、篮球&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;王五&quot;</span>,<span class="string">&quot;age&quot;</span>: 22,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;333@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;羽毛球、篮球、游泳、听音乐&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;赵六&quot;</span>,<span class="string">&quot;age&quot;</span>: 23,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;444@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;跑步、游泳&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;孙七&quot;</span>,<span class="string">&quot;age&quot;</span>: 24,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;555@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;听音乐、看电影&quot;</span>&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923104551405.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923104551405.png" alt="image-20200923104551405"></a></p><h4 id="测试搜索"><a href="#测试搜索" class="headerlink" title="测试搜索"></a>测试搜索</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;音乐&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923104653427.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923104653427.png" alt="image-20200923104653427"></a></p><h3 id="结构化查询"><a href="#结构化查询" class="headerlink" title="结构化查询"></a>结构化查询</h3><h4 id="term查询"><a href="#term查询" class="headerlink" title="term查询"></a>term查询</h4><p>term 主要用于精确匹配哪些值，比如数字，日期，布尔值或 not_analyzed 的字符串(未经分析的文本数据类型)：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123; <span class="string">&quot;term&quot;</span>: &#123; <span class="string">&quot;age&quot;</span>: 26 &#125;&#125;</span><br><span class="line">&#123; <span class="string">&quot;term&quot;</span>: &#123; <span class="string">&quot;date&quot;</span>: <span class="string">&quot;2014-09-01&quot;</span> &#125;&#125;</span><br><span class="line">&#123; <span class="string">&quot;term&quot;</span>: &#123; <span class="string">&quot;public&quot;</span>: <span class="literal">true</span> &#125;&#125;</span><br><span class="line">&#123; <span class="string">&quot;term&quot;</span>: &#123; <span class="string">&quot;tag&quot;</span>: <span class="string">&quot;full_text&quot;</span> &#125;&#125;</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;term&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;age&quot;</span>:20</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923104851159.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923104851159.png" alt="image-20200923104851159"></a></p><h4 id="terms查询"><a href="#terms查询" class="headerlink" title="terms查询"></a>terms查询</h4><p>terms 跟 term 有点类似，但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值，那么文档需要一起去 做匹配：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;terms&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;tag&quot;</span>:[</span><br><span class="line">            <span class="string">&quot;search&quot;</span>,</span><br><span class="line">            <span class="string">&quot;full_text&quot;</span>,</span><br><span class="line">            <span class="string">&quot;nosql&quot;</span></span><br><span class="line">        ]</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;terms&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;age&quot;</span>:[</span><br><span class="line">                20,</span><br><span class="line">                21</span><br><span class="line">            ]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923105030182.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923105030182.png" alt="image-20200923105030182"></a></p><h4 id="range查询"><a href="#range查询" class="headerlink" title="range查询"></a>range查询</h4><p>range 过滤允许我们按照指定范围查找一批数据：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;range&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;age&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;gte&quot;</span>:20,</span><br><span class="line">            <span class="string">&quot;lt&quot;</span>:30</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>范围操作符包含：</p><ul><li>gt : 大于</li><li>gte:: 大于等于</li><li>lt : 小于</li><li>lte: 小于等于</li></ul><p>示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;range&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;age&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;gte&quot;</span>:20,</span><br><span class="line">                <span class="string">&quot;lte&quot;</span>:22</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="exists-查询"><a href="#exists-查询" class="headerlink" title="exists 查询"></a>exists 查询</h4><p>exists 查询可以用于查找文档中是否包含指定字段或没有某个字段，类似于SQL语句中的IS_NULL 条件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;exists&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;field&quot;</span>: <span class="string">&quot;title&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这两个查询只是针对已经查出一批数据来，但是想区分出某个字段是否存在的时候使用。示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/user/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;exists&quot;</span>: &#123; <span class="comment">#必须包含</span></span><br><span class="line">            <span class="string">&quot;field&quot;</span>: <span class="string">&quot;card&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923105416339.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923105416339.png" alt="image-20200923105416339"></a></p><h4 id="match查询"><a href="#match查询" class="headerlink" title="match查询"></a>match查询</h4><p>match 查询是一个标准查询，不管你需要全文本查询还是精确查询基本上都要用到它。</p><p>如果你使用 match 查询一个全文本字段，它会在真正查询之前用分析器先分析match 一下查询字符：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;match&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;tweet&quot;</span>: <span class="string">&quot;About Search&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如果用match 下指定了一个确切值，在遇到数字，日期，布尔值或者not_analyzed 的字符串时，它将为你搜索你 给定的值：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123; <span class="string">&quot;match&quot;</span>: &#123; <span class="string">&quot;age&quot;</span>: 26 &#125;&#125;</span><br><span class="line">&#123; <span class="string">&quot;match&quot;</span>: &#123; <span class="string">&quot;date&quot;</span>: <span class="string">&quot;2014-09-01&quot;</span> &#125;&#125;</span><br><span class="line">&#123; <span class="string">&quot;match&quot;</span>: &#123; <span class="string">&quot;public&quot;</span>: <span class="literal">true</span> &#125;&#125;</span><br><span class="line">&#123; <span class="string">&quot;match&quot;</span>: &#123; <span class="string">&quot;tag&quot;</span>: <span class="string">&quot;full_text&quot;</span> &#125;&#125;</span><br></pre></td></tr></table></figure><h4 id="bool查询"><a href="#bool查询" class="headerlink" title="bool查询"></a>bool查询</h4><ul><li>bool 查询可以用来合并多个条件查询结果的布尔逻辑，它包含一下操作符：</li><li>must :: 多个查询条件的完全匹配,相当于 and 。</li><li>must_not :: 多个查询条件的相反匹配，相当于 not 。</li><li>should :: 至少有一个查询条件匹配, 相当于 or 。</li></ul><p>这些参数可以分别继承一个查询条件或者一个查询条件的数组：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;bool&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;must&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;term&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;folder&quot;</span>:<span class="string">&quot;inbox&quot;</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="string">&quot;must_not&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;term&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;tag&quot;</span>:<span class="string">&quot;spam&quot;</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="string">&quot;should&quot;</span>:[</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="string">&quot;term&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;starred&quot;</span>:<span class="literal">true</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="string">&quot;term&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;unread&quot;</span>:<span class="literal">true</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        ]</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="过滤查询"><a href="#过滤查询" class="headerlink" title="过滤查询"></a>过滤查询</h3><p>前面讲过结构化查询，Elasticsearch也支持过滤查询，如term、range、match等。</p><p>示例：查询年龄为20岁的用户。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;bool&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;filter&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;term&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;age&quot;</span>:20</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="查询和过滤的对比"><a href="#查询和过滤的对比" class="headerlink" title="查询和过滤的对比"></a>查询和过滤的对比</h4><ul><li>一条过滤语句会询问每个文档的字段值是否包含着特定值。</li><li>查询语句会询问每个文档的字段值与特定值的匹配程度如何。</li><li>一条查询语句会计算每个文档与查询语句的相关性，会给出一个相关性评分 _score，并且 按照相关性对匹 配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。</li><li>一个简单的文档列表，快速匹配运算并存入内存是十分方便的， 每个文档仅需要1个字节。这些缓存的过滤结果集与后续请求的结合使用是非常高效的。</li><li>查询语句不仅要查找相匹配的文档，还需要计算每个文档的相关性，所以一般来说查询语句要比 过滤语句更耗时，并且查询结果也不可缓存。</li></ul><h4 id="建议："><a href="#建议：" class="headerlink" title="建议："></a>建议：</h4><p>做精确匹配搜索时，最好用过滤语句，因为过滤语句可以缓存数据。</p><h2 id="中文分词"><a href="#中文分词" class="headerlink" title="中文分词"></a>中文分词</h2><h3 id="什么是分词"><a href="#什么是分词" class="headerlink" title="什么是分词"></a>什么是分词</h3><p>分词就是指将一个文本转化成一系列单词的过程，也叫文本分析，在Elasticsearch中称之为Analysis。</p><p>举例：我是中国人 –&gt; 我/是/中国人</p><h3 id="分词api"><a href="#分词api" class="headerlink" title="分词api"></a>分词api</h3><p>指定分词器进行分词</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">POST /_analyze</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;analyzer&quot;</span>:<span class="string">&quot;standard&quot;</span>,</span><br><span class="line">    <span class="string">&quot;text&quot;</span>:<span class="string">&quot;hello world&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>结果如下</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923110814505.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923110814505.png" alt="image-20200923110814505"></a></p><p>在结果中不仅可以看出分词的结果，还返回了该词在文本中的位置。</p><blockquote><p>指定索引分词</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/_analyze</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;analyzer&quot;</span>: <span class="string">&quot;standard&quot;</span>,</span><br><span class="line">    <span class="string">&quot;field&quot;</span>: <span class="string">&quot;hobby&quot;</span>,</span><br><span class="line">    <span class="string">&quot;text&quot;</span>: <span class="string">&quot;听音乐&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923110905001.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923110905001.png" alt="image-20200923110905001"></a></p><h3 id="中文分词难点"><a href="#中文分词难点" class="headerlink" title="中文分词难点"></a>中文分词难点</h3><p>中文分词的难点在于，在汉语中没有明显的词汇分界点，如在英语中，空格可以作为分隔符，如果分隔不正确就会造成歧义。如：</p><ul><li>我/爱/炒肉丝</li><li>我/爱/炒/肉丝</li></ul><p>常用中文分词器，IK、jieba、THULAC等，推荐使用IK分词器。</p><p>IK Analyzer是一个开源的，基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始，IKAnalyzer已经推出了3个大版本。最初，它是以开源项目Luence为应用主体的，结合词典分词和文法分析算法的中文分词组件。新版本的IK Analyzer 3.0则发展为面向Java的公用分词组件，独立于Lucene项目，同时提供了对Lucene的默认优化实现。</p><p>采用了特有的“正向迭代最细粒度切分算法“，具有80万字/秒的高速处理能力 采用了多子处理器分析模式，支持：英文字母（IP地址、Email、URL）、数字（日期，常用中文数量词，罗马数字，科学计数法），中文词汇（姓名、地名处理）等分词处理。 优化的词典存储，更小的内存占用。</p><p>IK分词器 Elasticsearch插件地址：<a href="https://github.com/medcl/elasticsearch-analysis-ik">https://github.com/medcl/elasticsearch-analysis-ik</a></p><h3 id="安装分词器"><a href="#安装分词器" class="headerlink" title="安装分词器"></a>安装分词器</h3><p>首先下载到最新的ik分词器：<a href="https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.9.1">下载地址</a></p><p>下载完成后，使用xftp工具，拷贝到服务器上</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#安装方法：将下载到的 es/plugins/ik 目录下</span></span><br><span class="line">mkdir es/plugins/ik</span><br><span class="line"></span><br><span class="line"><span class="comment">#解压</span></span><br><span class="line">unzip elasticsearch-analysis-ik-7.9.1.zip</span><br><span class="line"></span><br><span class="line"><span class="comment">#重启</span></span><br><span class="line">./bin/elasticsearch</span><br></pre></td></tr></table></figure><p>我们通过日志，发现它已经成功加载了ik分词器插件</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923113200826.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923113200826.png" alt="image-20200923113200826"></a></p><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">POST /_analyze</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;analyzer&quot;</span>: <span class="string">&quot;ik_max_word&quot;</span>,</span><br><span class="line">    <span class="string">&quot;text&quot;</span>: <span class="string">&quot;我是中国人&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们发现ik分词器已经成功分词完成</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923113222937.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923113222937.png" alt="image-20200923113222937"></a></p><h2 id="全文搜索-1"><a href="#全文搜索-1" class="headerlink" title="全文搜索"></a>全文搜索</h2><p>全文搜索两个最重要的方面是：</p><ul><li>相关性（Relevance） 它是评价查询与其结果间的相关程度，并根据这种相关程度对结果排名的一种能力，这 种计算方式可以是 TF/IDF 方法、地理位置邻近、模糊相似，或其他的某些算法。</li><li>分词（Analysis） 它是将文本块转换为有区别的、规范化的 token 的一个过程，目的是为了创建倒排索引以及查询倒排索引。</li></ul><h3 id="构造数据"><a href="#构造数据" class="headerlink" title="构造数据"></a>构造数据</h3><blockquote><p>ES 7.4 默认不在支持指定索引类型，默认索引类型是_doc</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">http://202.193.56.222:9200/itcast?include_type_name=<span class="literal">true</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;settings&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;index&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;number_of_shards&quot;</span>:<span class="string">&quot;1&quot;</span>,</span><br><span class="line">            <span class="string">&quot;number_of_replicas&quot;</span>:<span class="string">&quot;0&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;mappings&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;person&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;properties&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;name&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;type&quot;</span>:<span class="string">&quot;text&quot;</span></span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="string">&quot;age&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;type&quot;</span>:<span class="string">&quot;integer&quot;</span></span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="string">&quot;mail&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;type&quot;</span>:<span class="string">&quot;keyword&quot;</span></span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;type&quot;</span>:<span class="string">&quot;text&quot;</span>,</span><br><span class="line">                    <span class="string">&quot;analyzer&quot;</span>:<span class="string">&quot;ik_max_word&quot;</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后插入数据</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">POST http://202.193.56.222:9200/itcast/_bulk</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;张三&quot;</span>,<span class="string">&quot;age&quot;</span>: 20,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;111@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;羽毛球、乒乓球、足球&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;李四&quot;</span>,<span class="string">&quot;age&quot;</span>: 21,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;222@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;羽毛球、乒乓球、足球、篮球&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;王五&quot;</span>,<span class="string">&quot;age&quot;</span>: 22,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;333@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;羽毛球、篮球、游泳、听音乐&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;赵六&quot;</span>,<span class="string">&quot;age&quot;</span>: 23,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;444@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;跑步、游泳、篮球&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;itcast&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;person&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;孙七&quot;</span>,<span class="string">&quot;age&quot;</span>: 24,<span class="string">&quot;mail&quot;</span>: <span class="string">&quot;555@qq.com&quot;</span>,<span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;听音乐、看电影、羽毛球&quot;</span>&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923141912153.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923141912153.png" alt="image-20200923141912153"></a></p><h3 id="单词搜索"><a href="#单词搜索" class="headerlink" title="单词搜索"></a>单词搜索</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;音乐&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;highlight&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;fields&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>查询出来的结果如下，并且还带有高亮</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923142131426.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923142131426.png" alt="image-20200923142131426"></a></p><p>过程说明：</p><ul><li>检查字段类型<ul><li>爱好 hobby 字段是一个 text 类型（ 指定了IK分词器），这意味着查询字符串本身也应该被分词。</li></ul></li><li>分析查询字符串 。<ul><li>将查询的字符串 “音乐” 传入IK分词器中，输出的结果是单个项 音乐。因为只有一个单词项，所以 match 查询执行的是单个底层 term 查询。</li></ul></li><li>查找匹配文档 。<ul><li>用 term 查询在倒排索引中查找 “音乐” 然后获取一组包含该项的文档，本例的结果是文档：3 、5 。</li></ul></li><li>为每个文档评分 。<ul><li>用 term 查询计算每个文档相关度评分 _score ，这是种将 词频（term frequency，即词 “音乐” 在相关文档的hobby 字段中出现的频率）和 反向文档频率（inverse document frequency，即词 “音乐” 在所有文档的hobby 字段中出现的频率），以及字段的长度（即字段越短相关度越高）相结合的计算方式。</li></ul></li></ul><h3 id="多词搜索"><a href="#多词搜索" class="headerlink" title="多词搜索"></a>多词搜索</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;音乐 篮球&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;highlight&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;fields&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以看到，包含了“音乐”、“篮球”的数据都已经被搜索到了。可是，搜索的结果并不符合我们的预期，因为我们想搜索的是既包含“音乐”又包含“篮球”的用户，显然结果返回的“或”的关系。在Elasticsearch中，可以指定词之间的逻辑关系，如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;音乐 篮球&quot;</span></span><br><span class="line">            <span class="string">&quot;operator&quot;</span>:<span class="string">&quot;and&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;highlight&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;fields&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>通过这样的话，就会让两个关键字之间存在and关系了</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923142538105.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923142538105.png" alt="image-20200923142538105"></a></p><p>可以看到结果符合预期。</p><p>前面我们测试了“OR” 和 “AND”搜索，这是两个极端，其实在实际场景中，并不会选取这2个极端，更有可能是选取这种，或者说，只需要符合一定的相似度就可以查询到数据，在Elasticsearch中也支持这样的查询，通过 minimum_should_match来指定匹配度，如：70%；</p><p>示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;query&quot;</span>:<span class="string">&quot;游泳 羽毛球&quot;</span>,</span><br><span class="line">            <span class="string">&quot;minimum_should_match&quot;</span>:<span class="string">&quot;80%&quot;</span></span><br><span class="line">            &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">        <span class="string">&quot;highlight&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;fields&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;hobby&quot;</span>: &#123;&#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">#结果：省略显示</span></span><br><span class="line"><span class="string">&quot;hits&quot;</span>: &#123;</span><br><span class="line"><span class="string">&quot;total&quot;</span>: 4, <span class="comment">#相似度为80%的情况下，查询到4条数据</span></span><br><span class="line"><span class="string">&quot;max_score&quot;</span>: 1.621458,</span><br><span class="line"><span class="string">&quot;hits&quot;</span>: [</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">#设置40%进行测试：</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;query&quot;</span>:<span class="string">&quot;游泳 羽毛球&quot;</span>,</span><br><span class="line">            <span class="string">&quot;minimum_should_match&quot;</span>:<span class="string">&quot;40%&quot;</span></span><br><span class="line">            &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">&quot;highlight&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;fields&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>: &#123;&#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">#结果：</span></span><br><span class="line"><span class="string">&quot;hits&quot;</span>: &#123;</span><br><span class="line"><span class="string">&quot;total&quot;</span>: 5, <span class="comment">#相似度为40%的情况下，查询到5条数据</span></span><br><span class="line"><span class="string">&quot;max_score&quot;</span>: 1.621458,</span><br><span class="line"><span class="string">&quot;hits&quot;</span>: [</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>相似度应该多少合适，需要在实际的需求中进行反复测试，才可得到合理的值。</p><h3 id="组合搜索"><a href="#组合搜索" class="headerlink" title="组合搜索"></a>组合搜索</h3><p>在搜索时，也可以使用过滤器中讲过的bool组合查询，示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;bool&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;must&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;篮球&quot;</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">&quot;must_not&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;音乐&quot;</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">&quot;should&quot;</span>:[</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                        <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;游泳&quot;</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            ]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;highlight&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;fields&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>上面搜索的意思是： 搜索结果中必须包含篮球，不能包含音乐，如果包含了游泳，那么它的相似度更高。</p></blockquote><p>结果：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923145310698.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923145310698.png" alt="image-20200923145310698"></a></p><blockquote><p>评分的计算规则</p><p>bool 查询会为每个文档计算相关度评分 _score ， 再将所有匹配的 must 和 should 语句的分数 _score 求和，最后除以 must 和 should 语句的总数。</p><p>must_not 语句不会影响评分； 它的作用只是将不相关的文档排除。</p></blockquote><p>默认情况下，should中的内容不是必须匹配的，如果查询语句中没有must，那么就会至少匹配其中一个。当然了，也可以通过minimum_should_match参数进行控制，该值可以是数字也可以的百分比。</p><p>示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;bool&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;should&quot;</span>:[</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                        <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;游泳&quot;</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;,</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                        <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;篮球&quot;</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;,</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                        <span class="string">&quot;hobby&quot;</span>:<span class="string">&quot;音乐&quot;</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            ],</span><br><span class="line">            <span class="string">&quot;minimum_should_match&quot;</span>:2</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;highlight&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;fields&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>minimum_should_match为2，意思是should中的三个词，至少要满足2个。</p><h3 id="权重"><a href="#权重" class="headerlink" title="权重"></a>权重</h3><p>有些时候，我们可能需要对某些词增加权重来影响该条数据的得分。如下：</p><p>搜索关键字为“游泳篮球”，如果结果中包含了“音乐”权重为10，包含了“跑步”权重为2。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">POST /itcast/person/_search</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;query&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;bool&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;must&quot;</span>:&#123;</span><br><span class="line">                <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                    <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line">                        <span class="string">&quot;query&quot;</span>:<span class="string">&quot;游泳篮球&quot;</span>,</span><br><span class="line">                        <span class="string">&quot;operator&quot;</span>:<span class="string">&quot;and&quot;</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">&quot;should&quot;</span>:[</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                        <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line">                            <span class="string">&quot;query&quot;</span>:<span class="string">&quot;音乐&quot;</span>,</span><br><span class="line">                            <span class="string">&quot;boost&quot;</span>:10</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;,</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="string">&quot;match&quot;</span>:&#123;</span><br><span class="line">                        <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line">                            <span class="string">&quot;query&quot;</span>:<span class="string">&quot;跑步&quot;</span>,</span><br><span class="line">                            <span class="string">&quot;boost&quot;</span>:2</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            ]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;highlight&quot;</span>:&#123;</span><br><span class="line">        <span class="string">&quot;fields&quot;</span>:&#123;</span><br><span class="line">            <span class="string">&quot;hobby&quot;</span>:&#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="ElasticSearch集群"><a href="#ElasticSearch集群" class="headerlink" title="ElasticSearch集群"></a>ElasticSearch集群</h2><h3 id="集群节点"><a href="#集群节点" class="headerlink" title="集群节点"></a>集群节点</h3><p>ELasticsearch的集群是由多个节点组成的，通过cluster.name设置集群名称，并且用于区分其它的集群，每个节点通过node.name指定节点的名称。</p><p>在Elasticsearch中，节点的类型主要有4种：</p><ul><li>master节点<ul><li>配置文件中node.master属性为true(默认为true)，就有资格被选为master节点。master节点用于控制整个集群的操作。比如创建或删除索引，管理其它非master节点等。</li></ul></li><li>data节点<ul><li>配置文件中node.data属性为true(默认为true)，就有资格被设置成data节点。data节点主要用于执行数据相关的操作。比如文档的CRUD。</li></ul></li><li>客户端节点<ul><li>配置文件中node.master属性和node.data属性均为false。</li><li>该节点不能作为master节点，也不能作为data节点。</li><li>可以作为客户端节点，用于响应用户的请求，把请求转发到其他节点</li></ul></li><li>部落节点<ul><li>当一个节点配置tribe.*的时候，它是一个特殊的客户端，它可以连接多个集群，在所有连接的集群上执行 搜索和其他操作。</li></ul></li></ul><h3 id="搭建集群"><a href="#搭建集群" class="headerlink" title="搭建集群"></a>搭建集群</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#启动3个虚拟机，分别在3台虚拟机上部署安装Elasticsearch</span></span><br><span class="line">mkdir /itcast/es-cluster</span><br><span class="line"></span><br><span class="line"><span class="comment">#分发到其它机器</span></span><br><span class="line">scp -r es-cluster elsearch@192.168.40.134:/itcast</span><br><span class="line"></span><br><span class="line"><span class="comment">#node01的配置：</span></span><br><span class="line">cluster.name: es-itcast-cluster</span><br><span class="line">node.name: node01</span><br><span class="line">node.master: <span class="literal">true</span></span><br><span class="line">node.data: <span class="literal">true</span></span><br><span class="line">network.host: 0.0.0.0</span><br><span class="line">http.port: 9200</span><br><span class="line">discovery.zen.ping.unicast.hosts: [<span class="string">&quot;192.168.40.133&quot;</span>,<span class="string">&quot;192.168.40.134&quot;</span>,<span class="string">&quot;192.168.40.135&quot;</span>]</span><br><span class="line"><span class="comment"># 最小节点数</span></span><br><span class="line">discovery.zen.minimum_master_nodes: 2</span><br><span class="line"><span class="comment"># 跨域专用</span></span><br><span class="line">http.cors.enabled: <span class="literal">true</span></span><br><span class="line">http.cors.allow-origin: <span class="string">&quot;*&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#node02的配置：</span></span><br><span class="line">cluster.name: es-itcast-cluster</span><br><span class="line">node.name: node02</span><br><span class="line">node.master: <span class="literal">true</span></span><br><span class="line">node.data: <span class="literal">true</span></span><br><span class="line">network.host: 0.0.0.0</span><br><span class="line">http.port: 9200</span><br><span class="line">discovery.zen.ping.unicast.hosts: [<span class="string">&quot;192.168.40.133&quot;</span>,<span class="string">&quot;192.168.40.134&quot;</span>,<span class="string">&quot;192.168.40.135&quot;</span>]</span><br><span class="line">discovery.zen.minimum_master_nodes: 2</span><br><span class="line">http.cors.enabled: <span class="literal">true</span></span><br><span class="line">http.cors.allow-origin: <span class="string">&quot;*&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#node03的配置：</span></span><br><span class="line">cluster.name: es-itcast-cluster</span><br><span class="line">node.name: node02</span><br><span class="line">node.master: <span class="literal">true</span></span><br><span class="line">node.data: <span class="literal">true</span></span><br><span class="line">network.host: 0.0.0.0</span><br><span class="line">http.port: 9200</span><br><span class="line">discovery.zen.ping.unicast.hosts: [<span class="string">&quot;192.168.40.133&quot;</span>,<span class="string">&quot;192.168.40.134&quot;</span>,<span class="string">&quot;192.168.40.135&quot;</span>]</span><br><span class="line">discovery.zen.minimum_master_nodes: 2</span><br><span class="line">http.cors.enabled: <span class="literal">true</span></span><br><span class="line">http.cors.allow-origin: <span class="string">&quot;*&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#分别启动3个节点</span></span><br><span class="line">./elasticsearch</span><br></pre></td></tr></table></figure><p>查看集群</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923151823672.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923151823672.png" alt="image-20200923151823672"></a></p><p>创建索引：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923151851785.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923151851785.png" alt="image-20200923151851785"></a></p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923151935283.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923151935283.png" alt="image-20200923151935283"></a></p><p>查询集群状态：/_cluster/health 响应：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923151953227.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923151953227.png" alt="image-20200923151953227"></a></p><p>集群中有三种颜色</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152005930.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152005930.png" alt="image-20200923152005930"></a></p><h3 id="分片和副本"><a href="#分片和副本" class="headerlink" title="分片和副本"></a>分片和副本</h3><p>为了将数据添加到Elasticsearch，我们需要索引(index)——一个存储关联数据的地方。实际上，索引只是一个用来指向一个或多个分片(shards)的“逻辑命名空间(logical namespace)”.</p><ul><li>一个分片(shard)是一个最小级别“工作单元(worker unit)”,它只是保存了索引中所有数据的一部分。</li><li>我们需要知道是分片就是一个Lucene实例，并且它本身就是一个完整的搜索引擎。应用程序不会和它直接通 信。</li><li>分片可以是主分片(primary shard)或者是复制分片(replica shard)。</li><li>索引中的每个文档属于一个单独的主分片，所以主分片的数量决定了索引最多能存储多少数据。</li><li>复制分片只是主分片的一个副本，它可以防止硬件故障导致的数据丢失，同时可以提供读请求，比如搜索或者从别的shard取回文档。</li><li>当索引创建完成的时候，主分片的数量就固定了，但是复制分片的数量可以随时调整。</li></ul><h3 id="故障转移"><a href="#故障转移" class="headerlink" title="故障转移"></a>故障转移</h3><h4 id="将data节点停止"><a href="#将data节点停止" class="headerlink" title="将data节点停止"></a>将data节点停止</h4><p>这里选择将node02停止：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152229908.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152229908.png" alt="image-20200923152229908"></a></p><p>当前集群状态为黄色，表示主节点可用，副本节点不完全可用，过一段时间观察，发现节点列表中看不到node02，副本节点分配到了node01和node03，集群状态恢复到绿色。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152248547.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152248547.png" alt="image-20200923152248547"></a></p><p>将node02恢复： ./node02/1 bin/elasticsearch</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152328458.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152328458.png" alt="image-20200923152328458"></a></p><p>可以看到，node02恢复后，重新加入了集群，并且重新分配了节点信息。</p><h4 id="将master节点停止"><a href="#将master节点停止" class="headerlink" title="将master节点停止"></a>将master节点停止</h4><p>接下来，测试将node01停止，也就是将主节点停止。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152415890.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923152415890.png" alt="image-20200923152415890"></a></p><p>从结果中可以看出，集群对master进行了重新选举，选择node03为master。并且集群状态变成黄色。 等待一段时间后，集群状态从黄色变为了绿色：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923153343555.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923153343555.png" alt="image-20200923153343555"></a></p><p>恢复node01节点：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./node01/1 bin/elasticsearch</span><br></pre></td></tr></table></figure><p>重启之后，发现node01可以正常加入到集群中，集群状态依然为绿色：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923153415117.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923153415117.png" alt="image-20200923153415117"></a></p><p>特别说明：</p><p>如果在配置文件中discovery.zen.minimum_master_nodes设置的不是N/2+1时，会出现脑裂问题，之前宕机 的主节点恢复后不会加入到集群。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923153441693.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923153441693.png" alt="image-20200923153441693"></a></p><h3 id="分布式文档"><a href="#分布式文档" class="headerlink" title="分布式文档"></a>分布式文档</h3><h4 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h4><p>首先，来看个问题：</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923153556720.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923153556720.png" alt="image-20200923153556720"></a></p><p>如图所示：当我们想一个集群保存文档时，文档该存储到哪个节点呢？ 是随机吗？ 是轮询吗？实际上，在ELasticsearch中，会采用计算的方式来确定存储到哪个节点，计算公式如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shard = <span class="built_in">hash</span>(routing) % number_1 of_primary_shards</span><br></pre></td></tr></table></figure><p>其中：</p><ul><li>routing值是一个任意字符串，它默认是_id但也可以自定义。</li><li>这个routing字符串通过哈希函数生成一个数字，然后除以主切片的数量得到一个余数(remainder)，余数 的范围永远是0到number_of_primary_shards - 1，这个数字就是特定文档所在的分片</li></ul><p>这就是为什么创建了主分片后，不能修改的原因。</p><h4 id="文档的写操作"><a href="#文档的写操作" class="headerlink" title="文档的写操作"></a>文档的写操作</h4><p>新建、索引和删除请求都是写（write）操作，它们必须在主分片上成功完成才能复制分片上</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923155314424.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923155314424.png" alt="image-20200923155314424"></a></p><p>下面我们罗列在主分片和复制分片上成功新建、索引或删除一个文档必要的顺序步骤：</p><ol><li>客户端给Node 1 发送新建、索引或删除请求。</li><li>节点使用文档的_id 确定文档属于分片0 。它转发请求到Node 3 ，分片0 位于这个节点上。</li><li>Node 3 在主分片上执行请求，如果成功，它转发请求到相应的位于Node 1 和Node 2 的复制节点上。当所有 的复制节点报告成功， Node 3 报告成功到请求的节点，请求的节点再报告给客户端。</li></ol><p>客户端接收到成功响应的时候，文档的修改已经被应用于主分片和所有的复制分片。你的修改生效了。</p><h3 id="搜索文档"><a href="#搜索文档" class="headerlink" title="搜索文档"></a>搜索文档</h3><p>文档能够从主分片或任意一个复制分片被检索。</p><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923160046962.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923160046962.png" alt="image-20200923160046962"></a></p><p>下面我们罗列在主分片或复制分片上检索一个文档必要的顺序步骤：</p><ol><li>客户端给Node 1 发送get请求。</li><li>节点使用文档的_id 确定文档属于分片0 。分片0 对应的复制分片在三个节点上都有。此时，它转发请求到 Node 2 。</li><li>Node 2 返回文档(document)给Node 1 然后返回给客户端。对于读请求，为了平衡负载，请求节点会为每个请求选择不同的分片——它会循环所有分片副本。可能的情况是，一个被索引的文档已经存在于主分片上却还没来得及同步到复制分片上。这时复制分片会报告文档未找到，主分片会成功返回文档。一旦索引请求成功返回给用户，文档则在主分片和复制分片都是可用的。</li></ol><h3 id="全文搜索-2"><a href="#全文搜索-2" class="headerlink" title="全文搜索"></a>全文搜索</h3><p>对于全文搜索而言，文档可能分散在各个节点上，那么在分布式的情况下，如何搜索文档呢？</p><p>搜索，分为2个阶段，</p><ul><li>搜索（query）</li><li>取回（fetch）</li></ul><h4 id="搜索（query）"><a href="#搜索（query）" class="headerlink" title="搜索（query）"></a>搜索（query）</h4><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923161323235.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923161323235.png" alt="image-20200923161323235"></a></p><p>查询阶段包含以下三步：</p><ol><li>客户端发送一个search（搜索） 请求给Node 3 , Node 3 创建了一个长度为from+size 的空优先级队</li><li>Node 3 转发这个搜索请求到索引中每个分片的原本或副本。每个分片在本地执行这个查询并且结果将结果到 一个大小为from+size 的有序本地优先队列里去。</li><li>每个分片返回document的ID和它优先队列里的所有document的排序值给协调节点Node 3 。Node 3 把这些 值合并到自己的优先队列里产生全局排序结果。</li></ol><h4 id="取回-fetch"><a href="#取回-fetch" class="headerlink" title="取回 fetch"></a>取回 fetch</h4><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923161447618.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923161447618.png" alt="image-20200923161447618"></a></p><p>分发阶段由以下步骤构成：</p><ol><li>协调节点辨别出哪个document需要取回，并且向相关分片发出GET 请求。</li><li>每个分片加载document并且根据需要丰富（enrich）它们，然后再将document返回协调节点。</li><li>一旦所有的document都被取回，协调节点会将结果返回给客户端。</li></ol><h2 id="Java客户端"><a href="#Java客户端" class="headerlink" title="Java客户端"></a>Java客户端</h2><p>在Elasticsearch中，为java提供了2种客户端，一种是REST风格的客户端，另一种是Java API的客户端</p><h3 id="REST客户端"><a href="#REST客户端" class="headerlink" title="REST客户端"></a>REST客户端</h3><p>Elasticsearch提供了2种REST客户端，一种是低级客户端，一种是高级客户端。</p><ul><li>Java Low Level REST Client：官方提供的低级客户端。该客户端通过http来连接Elasticsearch集群。用户在使 用该客户端时需要将请求数据手动拼接成Elasticsearch所需JSON格式进行发送，收到响应时同样也需要将返回的JSON数据手动封装成对象。虽然麻烦，不过该客户端兼容所有的Elasticsearch版本。</li><li>Java High Level REST Client：官方提供的高级客户端。该客户端基于低级客户端实现，它提供了很多便捷的 API来解决低级客户端需要手动转换数据格式的问题。</li></ul><h3 id="构造数据-1"><a href="#构造数据-1" class="headerlink" title="构造数据"></a>构造数据</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">POST /haoke/house/_bulk</span><br><span class="line"></span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;house&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:<span class="string">&quot;1001&quot;</span>,<span class="string">&quot;title&quot;</span>:<span class="string">&quot;整租 · 南丹大楼 1居室 7500&quot;</span>,<span class="string">&quot;price&quot;</span>:<span class="string">&quot;7500&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;house&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:<span class="string">&quot;1002&quot;</span>,<span class="string">&quot;title&quot;</span>:<span class="string">&quot;陆家嘴板块，精装设计一室一厅，可拎包入住诚意租。&quot;</span>,<span class="string">&quot;price&quot;</span>:<span class="string">&quot;8500&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;house&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:<span class="string">&quot;1003&quot;</span>,<span class="string">&quot;title&quot;</span>:<span class="string">&quot;整租 · 健安坊 1居室 4050&quot;</span>,<span class="string">&quot;price&quot;</span>:<span class="string">&quot;7500&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;house&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:<span class="string">&quot;1004&quot;</span>,<span class="string">&quot;title&quot;</span>:<span class="string">&quot;整租 · 中凯城市之光+视野开阔+景色秀丽+拎包入住&quot;</span>,<span class="string">&quot;price&quot;</span>:<span class="string">&quot;6500&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;house&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:<span class="string">&quot;1005&quot;</span>,<span class="string">&quot;title&quot;</span>:<span class="string">&quot;整租 · 南京西路品质小区 21213三轨交汇 配套齐* 拎包入住&quot;</span>,<span class="string">&quot;price&quot;</span>:<span class="string">&quot;6000&quot;</span>&#125;</span><br><span class="line">&#123;<span class="string">&quot;index&quot;</span>:&#123;<span class="string">&quot;_index&quot;</span>:<span class="string">&quot;haoke&quot;</span>,<span class="string">&quot;_type&quot;</span>:<span class="string">&quot;house&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;id&quot;</span>:<span class="string">&quot;1006&quot;</span>,<span class="string">&quot;title&quot;</span>:<span class="string">&quot;祥康里 简约风格 *南户型 拎包入住 看房随时&quot;</span>,<span class="string">&quot;price&quot;</span>:<span class="string">&quot;7000&quot;</span>&#125;</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923162419395.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/1_ElasticSearch%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%89%E8%A3%85/images/image-20200923162419395.png" alt="image-20200923162419395"></a></p><h3 id="REST低级客户端"><a href="#REST低级客户端" class="headerlink" title="REST低级客户端"></a>REST低级客户端</h3><p>创建项目，加入依赖</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.example<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>Study_ElasticSearch_Code<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">source</span>&gt;</span>7<span class="tag">&lt;/<span class="name">source</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">target</span>&gt;</span>7<span class="tag">&lt;/<span class="name">target</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.elasticsearch.client<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>elasticsearch-rest-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>6.8.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.12<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.fasterxml.jackson.core<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jackson-databind<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.11.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><p>编写测试类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.core.JsonProcessingException;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.HttpHost;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.util.EntityUtils;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.Request;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.Response;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.RestClient;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.RestClientBuilder;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 使用低级客户端 访问</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: 陌溪</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@create</span>: 2020-09-23-16:33</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ESApi</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> RestClient restClient;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> ObjectMapper MAPPER = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 初始化</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        RestClientBuilder restClientBuilder = RestClient.builder(<span class="keyword">new</span> HttpHost(<span class="string">&quot;202.193.56.222&quot;</span>, <span class="number">9200</span>, <span class="string">&quot;http&quot;</span>));</span><br><span class="line">        <span class="keyword">this</span>.restClient = restClientBuilder.build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询集群状态</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testGetInfo</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        Request request = <span class="keyword">new</span> Request(<span class="string">&quot;GET&quot;</span>, <span class="string">&quot;/_cluster/state&quot;</span>);</span><br><span class="line">        request.addParameter(<span class="string">&quot;pretty&quot;</span>, <span class="string">&quot;true&quot;</span>);</span><br><span class="line">        Response response = <span class="keyword">this</span>.restClient.performRequest(request);</span><br><span class="line">        System.out.println(response.getStatusLine());</span><br><span class="line">        System.out.println(EntityUtils.toString(response.getEntity()));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据ID查询数据</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IOException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testGetHouseInfo</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        Request request = <span class="keyword">new</span> Request(<span class="string">&quot;GET&quot;</span>, <span class="string">&quot;/haoke/house/Z3CduXQBYpWein3CRFug&quot;</span>);</span><br><span class="line">        request.addParameter(<span class="string">&quot;pretty&quot;</span>, <span class="string">&quot;true&quot;</span>);</span><br><span class="line">        Response response = <span class="keyword">this</span>.restClient.performRequest(request);</span><br><span class="line">        System.out.println(response.getStatusLine());</span><br><span class="line">        System.out.println(EntityUtils.toString(response.getEntity()));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testCreateData</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        Request request = <span class="keyword">new</span> Request(<span class="string">&quot;POST&quot;</span>, <span class="string">&quot;/haoke/house&quot;</span>);</span><br><span class="line">        Map&lt;String, Object&gt; data = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        data.put(<span class="string">&quot;id&quot;</span>, <span class="string">&quot;2001&quot;</span>);</span><br><span class="line">        data.put(<span class="string">&quot;title&quot;</span>, <span class="string">&quot;张江高科&quot;</span>);</span><br><span class="line">        data.put(<span class="string">&quot;price&quot;</span>, <span class="string">&quot;3500&quot;</span>);</span><br><span class="line">        <span class="comment">// 写成JSON</span></span><br><span class="line">        request.setJsonEntity(MAPPER.writeValueAsString(data));</span><br><span class="line">        Response response = <span class="keyword">this</span>.restClient.performRequest(request);</span><br><span class="line">        System.out.println(response.getStatusLine());</span><br><span class="line">        System.out.println(EntityUtils.toString(response.getEntity()));</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 搜索数据</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSearchData</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        Request request = <span class="keyword">new</span> Request(<span class="string">&quot;POST&quot;</span>, <span class="string">&quot;/haoke/house/_search&quot;</span>);</span><br><span class="line">        String searchJson = <span class="string">&quot;&#123;\&quot;query\&quot;: &#123;\&quot;match\&quot;: &#123;\&quot;title\&quot;: \&quot;拎包入住\&quot;&#125;&#125;&#125;&quot;</span>;</span><br><span class="line">        request.setJsonEntity(searchJson);</span><br><span class="line">        request.addParameter(<span class="string">&quot;pretty&quot;</span>,<span class="string">&quot;true&quot;</span>);</span><br><span class="line">        Response response = <span class="keyword">this</span>.restClient.performRequest(request);</span><br><span class="line">        System.out.println(response.getStatusLine());</span><br><span class="line">        System.out.println(EntityUtils.toString(response.getEntity()));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        ESApi esApi = <span class="keyword">new</span> ESApi();</span><br><span class="line">        esApi.init();</span><br><span class="line"><span class="comment">//        esApi.testGetInfo();</span></span><br><span class="line"><span class="comment">//        esApi.testGetHouseInfo();</span></span><br><span class="line">        esApi.testCreateData();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="REST高级客户端"><a href="#REST高级客户端" class="headerlink" title="REST高级客户端"></a>REST高级客户端</h3><p>创建项目，引入依赖</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.elasticsearch.client<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>elasticsearch-rest-high-level-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>6.8.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>编写测试用例</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.HttpHost;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.util.EntityUtils;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.ActionListener;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.delete.DeleteRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.delete.DeleteResponse;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.get.GetRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.get.GetResponse;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.index.IndexRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.index.IndexResponse;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.search.SearchRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.search.SearchResponse;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.update.UpdateRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.update.UpdateResponse;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.*;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.common.Strings;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.common.unit.TimeValue;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.index.query.QueryBuilders;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.SearchHit;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.SearchHits;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.builder.SearchSourceBuilder;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.fetch.subphase.FetchSourceContext;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ES高级客户端</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: 陌溪</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@create</span>: 2020-09-23-16:56</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ESHightApi</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> RestHighLevelClient client;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        RestClientBuilder restClientBuilder = RestClient.builder(</span><br><span class="line">                <span class="keyword">new</span> HttpHost(<span class="string">&quot;202.193.56.222&quot;</span>, <span class="number">9200</span>, <span class="string">&quot;http&quot;</span>));</span><br><span class="line">        <span class="keyword">this</span>.client = <span class="keyword">new</span> RestHighLevelClient(restClientBuilder);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.client.close();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 新增文档，同步操作</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testCreate</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        Map&lt;String, Object&gt; data = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        data.put(<span class="string">&quot;id&quot;</span>, <span class="string">&quot;2002&quot;</span>);</span><br><span class="line">        data.put(<span class="string">&quot;title&quot;</span>, <span class="string">&quot;南京西路 拎包入住 一室一厅&quot;</span>);</span><br><span class="line">        data.put(<span class="string">&quot;price&quot;</span>, <span class="string">&quot;4500&quot;</span>);</span><br><span class="line">        IndexRequest indexRequest = <span class="keyword">new</span> IndexRequest(<span class="string">&quot;haoke&quot;</span>, <span class="string">&quot;house&quot;</span>)</span><br><span class="line">                .source(data);</span><br><span class="line">        IndexResponse indexResponse = <span class="keyword">this</span>.client.index(indexRequest,</span><br><span class="line">                RequestOptions.DEFAULT);</span><br><span class="line">        System.out.println(<span class="string">&quot;id-&gt;&quot;</span> + indexResponse.getId());</span><br><span class="line">        System.out.println(<span class="string">&quot;index-&gt;&quot;</span> + indexResponse.getIndex());</span><br><span class="line">        System.out.println(<span class="string">&quot;type-&gt;&quot;</span> + indexResponse.getType());</span><br><span class="line">        System.out.println(<span class="string">&quot;version-&gt;&quot;</span> + indexResponse.getVersion());</span><br><span class="line">        System.out.println(<span class="string">&quot;result-&gt;&quot;</span> + indexResponse.getResult());</span><br><span class="line">        System.out.println(<span class="string">&quot;shardInfo-&gt;&quot;</span> + indexResponse.getShardInfo());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 异步创建文档</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testCreateAsync</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        Map&lt;String, Object&gt; data = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        data.put(<span class="string">&quot;id&quot;</span>, <span class="string">&quot;2003&quot;</span>);</span><br><span class="line">        data.put(<span class="string">&quot;title&quot;</span>, <span class="string">&quot;南京东路 最新房源 二室一厅&quot;</span>);</span><br><span class="line">        data.put(<span class="string">&quot;price&quot;</span>, <span class="string">&quot;5500&quot;</span>);</span><br><span class="line">        IndexRequest indexRequest = <span class="keyword">new</span> IndexRequest(<span class="string">&quot;haoke&quot;</span>, <span class="string">&quot;house&quot;</span>)</span><br><span class="line">                .source(data);</span><br><span class="line">        <span class="keyword">this</span>.client.indexAsync(indexRequest, RequestOptions.DEFAULT, <span class="keyword">new</span></span><br><span class="line">                ActionListener&lt;IndexResponse&gt;() &#123;</span><br><span class="line">                    <span class="meta">@Override</span></span><br><span class="line">                    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span><span class="params">(IndexResponse indexResponse)</span> </span>&#123;</span><br><span class="line">                        System.out.println(<span class="string">&quot;id-&gt;&quot;</span> + indexResponse.getId());</span><br><span class="line">                        System.out.println(<span class="string">&quot;index-&gt;&quot;</span> + indexResponse.getIndex());</span><br><span class="line">                        System.out.println(<span class="string">&quot;type-&gt;&quot;</span> + indexResponse.getType());</span><br><span class="line">                        System.out.println(<span class="string">&quot;version-&gt;&quot;</span> + indexResponse.getVersion());</span><br><span class="line">                        System.out.println(<span class="string">&quot;result-&gt;&quot;</span> + indexResponse.getResult());</span><br><span class="line">                        System.out.println(<span class="string">&quot;shardInfo-&gt;&quot;</span> + indexResponse.getShardInfo());</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="meta">@Override</span></span><br><span class="line">                    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onFailure</span><span class="params">(Exception e)</span> </span>&#123;</span><br><span class="line">                        System.out.println(e);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;);</span><br><span class="line">        System.out.println(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">        Thread.sleep(<span class="number">20000</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testQuery</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        GetRequest getRequest = <span class="keyword">new</span> GetRequest(<span class="string">&quot;haoke&quot;</span>, <span class="string">&quot;house&quot;</span>,</span><br><span class="line">                <span class="string">&quot;GkpdE2gBCKv8opxuOj12&quot;</span>);</span><br><span class="line">        <span class="comment">// 指定返回的字段</span></span><br><span class="line">        String[] includes = <span class="keyword">new</span> String[]&#123;<span class="string">&quot;title&quot;</span>, <span class="string">&quot;id&quot;</span>&#125;;</span><br><span class="line">        String[] excludes = Strings.EMPTY_ARRAY;</span><br><span class="line">        FetchSourceContext fetchSourceContext =</span><br><span class="line">                <span class="keyword">new</span> FetchSourceContext(<span class="keyword">true</span>, includes, excludes);</span><br><span class="line">        getRequest.fetchSourceContext(fetchSourceContext);</span><br><span class="line">        GetResponse response = <span class="keyword">this</span>.client.get(getRequest, RequestOptions.DEFAULT);</span><br><span class="line">        System.out.println(<span class="string">&quot;数据 -&gt; &quot;</span> + response.getSource());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 判断是否存在</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testExists</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        GetRequest getRequest = <span class="keyword">new</span> GetRequest(<span class="string">&quot;haoke&quot;</span>, <span class="string">&quot;house&quot;</span>,</span><br><span class="line">                <span class="string">&quot;GkpdE2gBCKv8opxuOj12&quot;</span>);</span><br><span class="line"><span class="comment">// 不返回的字段</span></span><br><span class="line">        getRequest.fetchSourceContext(<span class="keyword">new</span> FetchSourceContext(<span class="keyword">false</span>));</span><br><span class="line">        <span class="keyword">boolean</span> exists = <span class="keyword">this</span>.client.exists(getRequest, RequestOptions.DEFAULT);</span><br><span class="line">        System.out.println(<span class="string">&quot;exists -&gt; &quot;</span> + exists);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除数据</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testDelete</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        DeleteRequest deleteRequest = <span class="keyword">new</span> DeleteRequest(<span class="string">&quot;haoke&quot;</span>, <span class="string">&quot;house&quot;</span>,</span><br><span class="line">                <span class="string">&quot;GkpdE2gBCKv8opxuOj12&quot;</span>);</span><br><span class="line">        DeleteResponse response = <span class="keyword">this</span>.client.delete(deleteRequest,</span><br><span class="line">                RequestOptions.DEFAULT);</span><br><span class="line">        System.out.println(response.status());<span class="comment">// OK or NOT_FOUND</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 更新数据</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testUpdate</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        UpdateRequest updateRequest = <span class="keyword">new</span> UpdateRequest(<span class="string">&quot;haoke&quot;</span>, <span class="string">&quot;house&quot;</span>,</span><br><span class="line">                <span class="string">&quot;G0pfE2gBCKv8opxuRz1y&quot;</span>);</span><br><span class="line">        Map&lt;String, Object&gt; data = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        data.put(<span class="string">&quot;title&quot;</span>, <span class="string">&quot;张江高科2&quot;</span>);</span><br><span class="line">        data.put(<span class="string">&quot;price&quot;</span>, <span class="string">&quot;5000&quot;</span>);</span><br><span class="line">        updateRequest.doc(data);</span><br><span class="line">        UpdateResponse response = <span class="keyword">this</span>.client.update(updateRequest,</span><br><span class="line">                RequestOptions.DEFAULT);</span><br><span class="line">        System.out.println(<span class="string">&quot;version -&gt; &quot;</span> + response.getVersion());</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 测试搜索</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSearch</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        SearchRequest searchRequest = <span class="keyword">new</span> SearchRequest(<span class="string">&quot;haoke&quot;</span>);</span><br><span class="line">        searchRequest.types(<span class="string">&quot;house&quot;</span>);</span><br><span class="line">        SearchSourceBuilder sourceBuilder = <span class="keyword">new</span> SearchSourceBuilder();</span><br><span class="line">        sourceBuilder.query(QueryBuilders.matchQuery(<span class="string">&quot;title&quot;</span>, <span class="string">&quot;拎包入住&quot;</span>));</span><br><span class="line">        sourceBuilder.from(<span class="number">0</span>);</span><br><span class="line">        sourceBuilder.size(<span class="number">5</span>);</span><br><span class="line">        sourceBuilder.timeout(<span class="keyword">new</span> TimeValue(<span class="number">60</span>, TimeUnit.SECONDS));</span><br><span class="line">        searchRequest.source(sourceBuilder);</span><br><span class="line">        SearchResponse search = <span class="keyword">this</span>.client.search(searchRequest,</span><br><span class="line">                RequestOptions.DEFAULT);</span><br><span class="line">        System.out.println(<span class="string">&quot;搜索到 &quot;</span> + search.getHits().totalHits + <span class="string">&quot; 条数据.&quot;</span>);</span><br><span class="line">        SearchHits hits = search.getHits();</span><br><span class="line">        <span class="keyword">for</span> (SearchHit hit : hits) &#123;</span><br><span class="line">            System.out.println(hit.getSourceAsString());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        ESHightApi esHightApi = <span class="keyword">new</span> ESHightApi();</span><br><span class="line">        esHightApi.init();</span><br><span class="line">        esHightApi.testCreate();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> elk </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>哈希表思路图解和代码实现</title>
      <link href="operation/hash/"/>
      <url>operation/hash/</url>
      
        <content type="html"><![CDATA[<h1 id="哈希表-散列-Google上机题"><a href="#哈希表-散列-Google上机题" class="headerlink" title="哈希表(散列)-Google上机题"></a>哈希表(散列)-Google上机题</h1><p>看一个实际需求，google公司的一个上机题:</p><p>有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址..),当输入该员工的id时,要求查找到该员工的 所有信息.</p><p>要求: 不使用数据库,尽量节省内存,速度越快越好=&gt;哈希表(散列)</p><p>散列表（Hash table，也叫哈希表），是根据关键码值(Key value)而直接进行访问的数据结构。也就是说，它通过把关键码值映射到表中一个位置来访问记录，以加快查找的速度。这个映射函数叫做散列函数，存放记录的数组叫做散列表。 15 111 % 15</p><p><a href="https://victorfengming.gitee.io/data_algorithm/img/QQ%E6%88%AA%E5%9B%BE20210223151004.png"><img src= "/img/loading.gif" data-lazy-src="https://victorfengming.gitee.io/data_algorithm/img/QQ%E6%88%AA%E5%9B%BE20210223151004.png" alt="img"></a></p><p><a href="https://victorfengming.gitee.io/data_algorithm/img/bilibili_line.png"><img src= "/img/loading.gif" data-lazy-src="https://victorfengming.gitee.io/data_algorithm/img/bilibili_line.png" alt="哔哩哔哩动画"></a></p><p><a href="https://victorfengming.gitee.io/data_algorithm/img/QQ%E6%88%AA%E5%9B%BE20210224110227.png"><img src= "/img/loading.gif" data-lazy-src="https://victorfengming.gitee.io/data_algorithm/img/QQ%E6%88%AA%E5%9B%BE20210224110227.png" alt="img"></a> <a href="https://victorfengming.gitee.io/data_algorithm/img/QQ%E6%88%AA%E5%9B%BE20210224110315.png"><img src= "/img/loading.gif" data-lazy-src="https://victorfengming.gitee.io/data_algorithm/img/QQ%E6%88%AA%E5%9B%BE20210224110315.png" alt="img"></a></p><p><a href="https://victorfengming.gitee.io/data_algorithm/img/bilibili_line.png"><img src= "/img/loading.gif" data-lazy-src="https://victorfengming.gitee.io/data_algorithm/img/bilibili_line.png" alt="哔哩哔哩动画"></a></p><blockquote><p>哈希表就是数组里面存储链表</p></blockquote><h2 id="google公司的一个上机题"><a href="#google公司的一个上机题" class="headerlink" title="google公司的一个上机题:"></a>google公司的一个上机题:</h2><p>有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,名字,住址..),当输入该员工的id时,要求查找到该员工的 所有信息.</p><h2 id="要求"><a href="#要求" class="headerlink" title="要求:"></a>要求:</h2><p>不使用数据库,,速度越快越好=&gt;哈希表(散列) 添加时，保证按照id从低到高插入 [课后思考：如果id不是从低到高插入，但要求各条链表仍是从低到高，怎么解决?]</p><ol><li>使用链表来实现哈希表, 该链表不带表头[即: 链表的第一个结点就存放雇员信息]</li><li>思路分析并画出示意图</li><li>代码实现[增删改查(显示所有员工，按id查询)]</li></ol><blockquote><p>// 哈希表之所以能够提高效率,是因为他能够同时管理多个链表</p></blockquote><h2 id="Emp"><a href="#Emp" class="headerlink" title="Emp"></a>Emp</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 表示一个雇员</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Emp</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> id;</span><br><span class="line">    <span class="keyword">public</span> String name;</span><br><span class="line">    <span class="keyword">public</span> Emp next;<span class="comment">//next 默认为空</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Emp</span><span class="params">(<span class="keyword">int</span> id, String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.id = id;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="HashTab"><a href="#HashTab" class="headerlink" title="HashTab"></a>HashTab</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">///创建hashTab 管理多条链表</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HashTab</span></span>&#123;</span><br><span class="line">    <span class="comment">// 数组里面放的是链表</span></span><br><span class="line">    <span class="keyword">private</span> EmpLinkedList[] empLinkedListArray;</span><br><span class="line">    <span class="comment">//</span></span><br><span class="line">    <span class="keyword">private</span> Integer size = <span class="number">7</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 构造器</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">HashTab</span><span class="params">(<span class="keyword">int</span> size)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 初始化empLinkedListArray</span></span><br><span class="line">        empLinkedListArray = <span class="keyword">new</span> EmpLinkedList[size];</span><br><span class="line">        <span class="comment">// ? 留一个坑</span></span><br><span class="line">        <span class="comment">// 这里能直接用么</span></span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">        * add:添加雇员</span></span><br><span class="line"><span class="comment">        list:显示雇员</span></span><br><span class="line"><span class="comment">        exit:退出雇员</span></span><br><span class="line"><span class="comment">        add</span></span><br><span class="line"><span class="comment">        输入id</span></span><br><span class="line"><span class="comment">        tom</span></span><br><span class="line"><span class="comment">        Exception in thread &quot;main&quot; java.util.InputMismatchException</span></span><br><span class="line"><span class="comment">            at java.util.Scanner.throwFor(Scanner.java:864)</span></span><br><span class="line"><span class="comment">            at java.util.Scanner.next(Scanner.java:1485)</span></span><br><span class="line"><span class="comment">            at java.util.Scanner.nextInt(Scanner.java:2117)</span></span><br><span class="line"><span class="comment">            at java.util.Scanner.nextInt(Scanner.java:2076)</span></span><br><span class="line"><span class="comment">            at com.atguigu.hashtab.HashTabDemo.main(HashTabDemo.java:30)</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">        Process finished with exit code 1</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">                * */</span></span><br><span class="line">        <span class="comment">// 这个时候不要忘了, 分别初始化 每个链表</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">            <span class="comment">// 数组中的每一个元素都需要创建一把</span></span><br><span class="line">            empLinkedListArray[i] = <span class="keyword">new</span> EmpLinkedList();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 添加雇员</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Emp emp)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 根据员工的id,得到该员工应当加入到,哪条链表</span></span><br><span class="line">        <span class="keyword">int</span> empLinkedListNO = hashFun(emp.id);</span><br><span class="line">        <span class="comment">// 将emp 添加到对应的链表中</span></span><br><span class="line">        empLinkedListArray[empLinkedListNO].add(emp);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 不管你是什么操作,总是要找链表</span></span><br><span class="line">    <span class="comment">// 遍历所有的链表</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">list</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 遍历Hash表</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">            empLinkedListArray[i].list(i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 编写一个散列函数</span></span><br><span class="line">    <span class="comment">// 散列函数有很多种写法</span></span><br><span class="line">    <span class="comment">// 这里使用简单的方法-取模法</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hashFun</span><span class="params">(<span class="keyword">int</span> id)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> id % size;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 更根据输入的id,查找雇员</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">findEmpById</span><span class="params">(<span class="keyword">int</span> id)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 使用散列函数确定到哪条链表查找</span></span><br><span class="line">        <span class="keyword">int</span> empLinkedListNO = hashFun(id);</span><br><span class="line">        Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id);</span><br><span class="line">        <span class="keyword">if</span> (emp != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 说明找到了</span></span><br><span class="line">            System.out.println(<span class="string">&quot;找到了该雇员&quot;</span>);</span><br><span class="line">            System.out.printf(<span class="string">&quot;在第%d条链表中找到了该雇员,id = %d&quot;</span>,id,empLinkedListNO+<span class="number">1</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;在哈希表中,没有找到该雇员~&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="EmpLinkedList"><a href="#EmpLinkedList" class="headerlink" title="EmpLinkedList"></a>EmpLinkedList</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">EmpLinkedList</span></span>&#123;</span><br><span class="line">    <span class="comment">// 头指针, 执行第一个Emp,因此我们这个链表的head,是直接 指向第一个Emp</span></span><br><span class="line">    <span class="keyword">private</span> Emp head;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//添加雇员到链表</span></span><br><span class="line">    <span class="comment">// 说明.</span></span><br><span class="line">    <span class="comment">// 1. 假定,当添加雇员的时候,id是自增长的,即id 的分配总是从小到大</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Emp emp)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 如果是添加第一个雇员</span></span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            head = emp;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 如果不是添加第一个雇员,则使用一个辅助的指针,帮助定位到最后</span></span><br><span class="line">        Emp currEmp = head;</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (currEmp.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 说明到链表最后</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 后移</span></span><br><span class="line">            currEmp = currEmp.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 退出时,直接将emp 加入链表</span></span><br><span class="line">        currEmp.next = emp;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 遍历链表的雇员信息</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">list</span><span class="params">(<span class="keyword">int</span> no)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 判断是否为空</span></span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 说明链表为空</span></span><br><span class="line">            System.out.println(<span class="string">&quot;当前链&quot;</span>+no+<span class="string">&quot;表为空!&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 没有空</span></span><br><span class="line"><span class="comment">//        打印信息</span></span><br><span class="line">        System.out.println(<span class="string">&quot;当前链&quot;</span>+no+<span class="string">&quot;表的信息为&quot;</span>);</span><br><span class="line">        <span class="comment">// 辅助指针</span></span><br><span class="line">        Emp currEmp = head;</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            System.out.printf(<span class="string">&quot;=&gt; id =%d name = %s\t&quot;</span>,currEmp.id,currEmp.name);</span><br><span class="line">            <span class="keyword">if</span> (currEmp.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 说明,currEmp 已经是最后节点</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 后移 遍历</span></span><br><span class="line">            currEmp = currEmp.next;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     *     // 根据id 查找雇员</span></span><br><span class="line"><span class="comment">     *    // 如果查找到 ,就返回Emp,如果没有找打到,就返回null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Emp <span class="title">findEmpById</span><span class="params">(<span class="keyword">int</span> id)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 判断链表是否为空</span></span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;链表为空&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//辅助指针</span></span><br><span class="line">        Emp curEmp = head;</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            <span class="comment">//</span></span><br><span class="line">            <span class="keyword">if</span> (curEmp.id == id) &#123;</span><br><span class="line">                <span class="comment">// 找到</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="comment">//  这个时候,currEmp就指向了要查找的雇员</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 退出</span></span><br><span class="line">            <span class="keyword">if</span> (curEmp.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 说明遍历当前链表没有找到该雇员</span></span><br><span class="line">                curEmp = <span class="keyword">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 后移</span></span><br><span class="line">            curEmp = curEmp.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> curEmp;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="主函数"><a href="#主函数" class="headerlink" title="主函数"></a>主函数</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 创建哈希表</span></span><br><span class="line">    HashTab hashTab = <span class="keyword">new</span> HashTab(<span class="number">7</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 写一个简单的菜单来测试</span></span><br><span class="line">    String key = <span class="string">&quot;&quot;</span>;</span><br><span class="line">    Scanner scanner = <span class="keyword">new</span> Scanner(System.in);</span><br><span class="line">    <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;add:添加雇员&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;list:显示雇员&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;find:查找雇员&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;exit:退出雇员&quot;</span>);</span><br><span class="line"></span><br><span class="line">        key = scanner.next();</span><br><span class="line">        <span class="keyword">switch</span> (key) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;add&quot;</span>:</span><br><span class="line">                System.out.println(<span class="string">&quot;输入id&quot;</span>);</span><br><span class="line">                <span class="keyword">int</span> id = scanner.nextInt();</span><br><span class="line">                System.out.println(<span class="string">&quot;输入名字&quot;</span>);</span><br><span class="line">                String name = scanner.next();</span><br><span class="line">                <span class="comment">// 创建雇员</span></span><br><span class="line">                Emp emp = <span class="keyword">new</span> Emp(id, name);</span><br><span class="line">                hashTab.add(emp);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;list&quot;</span>:</span><br><span class="line">                hashTab.list();</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;find&quot;</span>:</span><br><span class="line">                System.out.println(<span class="string">&quot;输入id&quot;</span>);</span><br><span class="line">                <span class="keyword">int</span> findId = scanner.nextInt();</span><br><span class="line">                hashTab.findEmpById(findId);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;exit&quot;</span>:</span><br><span class="line">                scanner.close();</span><br><span class="line">                System.exit(<span class="number">0</span>);</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br></pre></td><td class="code"><pre><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">1</span><br><span class="line">输入名字</span><br><span class="line">tom</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">2</span><br><span class="line">输入名字</span><br><span class="line">jack</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">3</span><br><span class="line">输入名字</span><br><span class="line">pin</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">6</span><br><span class="line">输入名字</span><br><span class="line">nanc</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">list</span><br><span class="line">当前链0表为空!</span><br><span class="line">当前链1表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;1 name &#x3D; tom</span><br><span class="line">当前链2表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;2 name &#x3D; jack</span><br><span class="line">当前链3表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;3 name &#x3D; pin</span><br><span class="line">当前链4表为空!</span><br><span class="line">当前链5表为空!</span><br><span class="line">当前链6表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;6 name &#x3D; nanc</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">123</span><br><span class="line">输入名字</span><br><span class="line">sme</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">list</span><br><span class="line">当前链0表为空!</span><br><span class="line">当前链1表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;1 name &#x3D; tom</span><br><span class="line">当前链2表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;2 name &#x3D; jack</span><br><span class="line">当前链3表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;3 name &#x3D; pin</span><br><span class="line">当前链4表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;123 name &#x3D; sme</span><br><span class="line">当前链5表为空!</span><br><span class="line">当前链6表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;6 name &#x3D; nanc</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">678</span><br><span class="line">输入名字</span><br><span class="line">vicr</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">list</span><br><span class="line">当前链0表为空!</span><br><span class="line">当前链1表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;1 name &#x3D; tom</span><br><span class="line">当前链2表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;2 name &#x3D; jack</span><br><span class="line">当前链3表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;3 name &#x3D; pin</span><br><span class="line">当前链4表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;123 name &#x3D; sme</span><br><span class="line">当前链5表为空!</span><br><span class="line">当前链6表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;6 name &#x3D; nanc&#x3D;&gt; id &#x3D;678 name &#x3D; vicr</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">389</span><br><span class="line">输入名字</span><br><span class="line">wef</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">9</span><br><span class="line">输入名字</span><br><span class="line">zho</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">list</span><br><span class="line">当前链0表为空!</span><br><span class="line">当前链1表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;1 name &#x3D; tom</span><br><span class="line">当前链2表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;2 name &#x3D; jack&#x3D;&gt; id &#x3D;9 name &#x3D; zho</span><br><span class="line">当前链3表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;3 name &#x3D; pin</span><br><span class="line">当前链4表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;123 name &#x3D; sme&#x3D;&gt; id &#x3D;389 name &#x3D; wef</span><br><span class="line">当前链5表为空!</span><br><span class="line">当前链6表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;6 name &#x3D; nanc&#x3D;&gt; id &#x3D;678 name &#x3D; vicr</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">34</span><br><span class="line">输入名字</span><br><span class="line">mach</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">list</span><br><span class="line">当前链0表为空!</span><br><span class="line">当前链1表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;1 name &#x3D; tom</span><br><span class="line">当前链2表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;2 name &#x3D; jack&#x3D;&gt; id &#x3D;9 name &#x3D; zho</span><br><span class="line">当前链3表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;3 name &#x3D; pin</span><br><span class="line">当前链4表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;123 name &#x3D; sme&#x3D;&gt; id &#x3D;389 name &#x3D; wef</span><br><span class="line">当前链5表为空!</span><br><span class="line">当前链6表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;6 name &#x3D; nanc&#x3D;&gt; id &#x3D;678 name &#x3D; vicr&#x3D;&gt; id &#x3D;34 name &#x3D; mach</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">find</span><br><span class="line">输入id</span><br><span class="line">8</span><br><span class="line">Exception in thread &quot;main&quot; java.lang.NullPointerException</span><br><span class="line">at com.atguigu.hashtab.EmpLinkedList.findEmpById(HashTabDemo.java:237)</span><br><span class="line">at com.atguigu.hashtab.HashTab.findEmpById(HashTabDemo.java:128)</span><br><span class="line">at com.atguigu.hashtab.HashTabDemo.main(HashTabDemo.java:44)</span><br><span class="line"></span><br><span class="line">Process finished with exit code 1</span><br><span class="line"></span><br></pre></td></tr></table></figure><blockquote><p>最后这里置空要 加上break</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (curEmp.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 说明遍历当前链表没有找到该雇员</span></span><br><span class="line">                curEmp = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br></pre></td></tr></table></figure><blockquote><p>这下就可以了</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">1</span><br><span class="line">输入名字</span><br><span class="line">tom</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">2</span><br><span class="line">输入名字</span><br><span class="line">nancy</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add4</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">add</span><br><span class="line">输入id</span><br><span class="line">4</span><br><span class="line">输入名字</span><br><span class="line">victor</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">list</span><br><span class="line">当前链0表为空!</span><br><span class="line">当前链1表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;1 name &#x3D; tom</span><br><span class="line">当前链2表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;2 name &#x3D; nancy</span><br><span class="line">当前链3表为空!</span><br><span class="line">当前链4表的信息为</span><br><span class="line">&#x3D;&gt; id &#x3D;4 name &#x3D; victor</span><br><span class="line">当前链5表为空!</span><br><span class="line">当前链6表为空!</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">find</span><br><span class="line">输入id</span><br><span class="line">6</span><br><span class="line">链表为空</span><br><span class="line">在哈希表中,没有找到该雇员~</span><br><span class="line">add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line">find</span><br><span class="line">输入id</span><br><span class="line">4</span><br><span class="line">找到了该雇员</span><br><span class="line">在第4条链表中找到了该雇员,id &#x3D; 5add:添加雇员</span><br><span class="line">list:显示雇员</span><br><span class="line">find:查找雇员</span><br><span class="line">exit:退出雇员</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.atguigu.hashtab;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Scanner;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName:  &lt;br/&gt;</span></span><br><span class="line"><span class="comment"> * Description:  &lt;br/&gt;</span></span><br><span class="line"><span class="comment"> * Date: 2021-02-24 13:10 &lt;br/&gt;</span></span><br><span class="line"><span class="comment"> * &lt;br/&gt;</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> data_algorithm</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> com.atguigu.hashtab</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HashTabDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建哈希表</span></span><br><span class="line">        HashTab hashTab = <span class="keyword">new</span> HashTab(<span class="number">7</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 写一个简单的菜单来测试</span></span><br><span class="line">        String key = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        Scanner scanner = <span class="keyword">new</span> Scanner(System.in);</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;add:添加雇员&quot;</span>);</span><br><span class="line">            System.out.println(<span class="string">&quot;list:显示雇员&quot;</span>);</span><br><span class="line">            System.out.println(<span class="string">&quot;find:查找雇员&quot;</span>);</span><br><span class="line">            System.out.println(<span class="string">&quot;exit:退出雇员&quot;</span>);</span><br><span class="line"></span><br><span class="line">            key = scanner.next();</span><br><span class="line">            <span class="keyword">switch</span> (key) &#123;</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&quot;add&quot;</span>:</span><br><span class="line">                    System.out.println(<span class="string">&quot;输入id&quot;</span>);</span><br><span class="line">                    <span class="keyword">int</span> id = scanner.nextInt();</span><br><span class="line">                    System.out.println(<span class="string">&quot;输入名字&quot;</span>);</span><br><span class="line">                    String name = scanner.next();</span><br><span class="line">                    <span class="comment">// 创建雇员</span></span><br><span class="line">                    Emp emp = <span class="keyword">new</span> Emp(id, name);</span><br><span class="line">                    hashTab.add(emp);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&quot;list&quot;</span>:</span><br><span class="line">                    hashTab.list();</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&quot;find&quot;</span>:</span><br><span class="line">                    System.out.println(<span class="string">&quot;输入id&quot;</span>);</span><br><span class="line">                    <span class="keyword">int</span> findId = scanner.nextInt();</span><br><span class="line">                    hashTab.findEmpById(findId);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&quot;exit&quot;</span>:</span><br><span class="line">                    scanner.close();</span><br><span class="line">                    System.exit(<span class="number">0</span>);</span><br><span class="line">                <span class="keyword">default</span>:</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">///创建hashTab 管理多条链表</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HashTab</span></span>&#123;</span><br><span class="line">    <span class="comment">// 数组里面放的是链表</span></span><br><span class="line">    <span class="keyword">private</span> EmpLinkedList[] empLinkedListArray;</span><br><span class="line">    <span class="comment">//</span></span><br><span class="line">    <span class="keyword">private</span> Integer size = <span class="number">7</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 构造器</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">HashTab</span><span class="params">(<span class="keyword">int</span> size)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 初始化empLinkedListArray</span></span><br><span class="line">        empLinkedListArray = <span class="keyword">new</span> EmpLinkedList[size];</span><br><span class="line">        <span class="comment">// ? 留一个坑</span></span><br><span class="line">        <span class="comment">// 这里能直接用么</span></span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">        * add:添加雇员</span></span><br><span class="line"><span class="comment">        list:显示雇员</span></span><br><span class="line"><span class="comment">        exit:退出雇员</span></span><br><span class="line"><span class="comment">        add</span></span><br><span class="line"><span class="comment">        输入id</span></span><br><span class="line"><span class="comment">        tom</span></span><br><span class="line"><span class="comment">        Exception in thread &quot;main&quot; java.util.InputMismatchException</span></span><br><span class="line"><span class="comment">            at java.util.Scanner.throwFor(Scanner.java:864)</span></span><br><span class="line"><span class="comment">            at java.util.Scanner.next(Scanner.java:1485)</span></span><br><span class="line"><span class="comment">            at java.util.Scanner.nextInt(Scanner.java:2117)</span></span><br><span class="line"><span class="comment">            at java.util.Scanner.nextInt(Scanner.java:2076)</span></span><br><span class="line"><span class="comment">            at com.atguigu.hashtab.HashTabDemo.main(HashTabDemo.java:30)</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">        Process finished with exit code 1</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">                * */</span></span><br><span class="line">        <span class="comment">// 这个时候不要忘了, 分别初始化 每个链表</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">            <span class="comment">// 数组中的每一个元素都需要创建一把</span></span><br><span class="line">            empLinkedListArray[i] = <span class="keyword">new</span> EmpLinkedList();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 添加雇员</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Emp emp)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 根据员工的id,得到该员工应当加入到,哪条链表</span></span><br><span class="line">        <span class="keyword">int</span> empLinkedListNO = hashFun(emp.id);</span><br><span class="line">        <span class="comment">// 将emp 添加到对应的链表中</span></span><br><span class="line">        empLinkedListArray[empLinkedListNO].add(emp);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 不管你是什么操作,总是要找链表</span></span><br><span class="line">    <span class="comment">// 遍历所有的链表</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">list</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 遍历Hash表</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">            empLinkedListArray[i].list(i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 编写一个散列函数</span></span><br><span class="line">    <span class="comment">// 散列函数有很多种写法</span></span><br><span class="line">    <span class="comment">// 这里使用简单的方法-取模法</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hashFun</span><span class="params">(<span class="keyword">int</span> id)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> id % size;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 更根据输入的id,查找雇员</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">findEmpById</span><span class="params">(<span class="keyword">int</span> id)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 使用散列函数确定到哪条链表查找</span></span><br><span class="line">        <span class="keyword">int</span> empLinkedListNO = hashFun(id);</span><br><span class="line">        Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id);</span><br><span class="line">        <span class="keyword">if</span> (emp != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 说明找到了</span></span><br><span class="line">            System.out.println(<span class="string">&quot;找到了该雇员&quot;</span>);</span><br><span class="line">            System.out.printf(<span class="string">&quot;在第%d条链表中找到了该雇员,id = %d&quot;</span>,id,empLinkedListNO+<span class="number">1</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;在哈希表中,没有找到该雇员~&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 表示一个雇员</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Emp</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> id;</span><br><span class="line">    <span class="keyword">public</span> String name;</span><br><span class="line">    <span class="keyword">public</span> Emp next;<span class="comment">//next 默认为空</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Emp</span><span class="params">(<span class="keyword">int</span> id, String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.id = id;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">EmpLinkedList</span></span>&#123;</span><br><span class="line">    <span class="comment">// 头指针, 执行第一个Emp,因此我们这个链表的head,是直接 指向第一个Emp</span></span><br><span class="line">    <span class="keyword">private</span> Emp head;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//添加雇员到链表</span></span><br><span class="line">    <span class="comment">// 说明.</span></span><br><span class="line">    <span class="comment">// 1. 假定,当添加雇员的时候,id是自增长的,即id 的分配总是从小到大</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Emp emp)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 如果是添加第一个雇员</span></span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            head = emp;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 如果不是添加第一个雇员,则使用一个辅助的指针,帮助定位到最后</span></span><br><span class="line">        Emp currEmp = head;</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (currEmp.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 说明到链表最后</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 后移</span></span><br><span class="line">            currEmp = currEmp.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 退出时,直接将emp 加入链表</span></span><br><span class="line">        currEmp.next = emp;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 遍历链表的雇员信息</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">list</span><span class="params">(<span class="keyword">int</span> no)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 判断是否为空</span></span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 说明链表为空</span></span><br><span class="line">            System.out.println(<span class="string">&quot;当前链&quot;</span>+no+<span class="string">&quot;表为空!&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 没有空</span></span><br><span class="line"><span class="comment">//        打印信息</span></span><br><span class="line">        System.out.println(<span class="string">&quot;当前链&quot;</span>+no+<span class="string">&quot;表的信息为&quot;</span>);</span><br><span class="line">        <span class="comment">// 辅助指针</span></span><br><span class="line">        Emp currEmp = head;</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            System.out.printf(<span class="string">&quot;=&gt; id =%d name = %s\t&quot;</span>,currEmp.id,currEmp.name);</span><br><span class="line">            <span class="keyword">if</span> (currEmp.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 说明,currEmp 已经是最后节点</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 后移 遍历</span></span><br><span class="line">            currEmp = currEmp.next;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     *     // 根据id 查找雇员</span></span><br><span class="line"><span class="comment">     *    // 如果查找到 ,就返回Emp,如果没有找打到,就返回null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Emp <span class="title">findEmpById</span><span class="params">(<span class="keyword">int</span> id)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 判断链表是否为空</span></span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;链表为空&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//辅助指针</span></span><br><span class="line">        Emp curEmp = head;</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            <span class="comment">//</span></span><br><span class="line">            <span class="keyword">if</span> (curEmp.id == id) &#123;</span><br><span class="line">                <span class="comment">// 找到</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="comment">//  这个时候,currEmp就指向了要查找的雇员</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 退出</span></span><br><span class="line">            <span class="keyword">if</span> (curEmp.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 说明遍历当前链表没有找到该雇员</span></span><br><span class="line">                curEmp = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 后移</span></span><br><span class="line">            curEmp = curEmp.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> curEmp;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="扩展"><a href="#扩展" class="headerlink" title="扩展"></a>扩展</h2><p>删除功能???</p>]]></content>
      
      
      
        <tags>
            
            <tag> summer </tag>
            
            <tag> java </tag>
            
            <tag> algorithm </tag>
            
            <tag> 数据结构 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Kibana入门安装与介绍</title>
      <link href="operation/kibana/"/>
      <url>operation/kibana/</url>
      
        <content type="html"><![CDATA[<h1 id="Kibana入门"><a href="#Kibana入门" class="headerlink" title="Kibana入门"></a>Kibana入门</h1><p>Kibana 是一款开源的数据分析和可视化平台，它是 Elastic Stack 成员之一，设计用于和 Elasticsearch 协作。您可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互操作。您可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现。</p><p>官网：<a href="https://www.elastic.co/cn/kibana">https://www.elastic.co/cn/kibana</a></p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924193926486.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924193926486.png" alt="image-20200924193926486"></a></p><h2 id="配置和安装"><a href="#配置和安装" class="headerlink" title="配置和安装"></a>配置和安装</h2><p>到下载地址，选择对应的版本：<a href="https://www.elastic.co/cn/downloads/kibana">https://www.elastic.co/cn/downloads/kibana</a></p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924194324366.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924194324366.png" alt="image-20200924194324366"></a>下载完成后，将文件拷贝到我们的服务器上，然后解压</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 解压</span></span><br><span class="line">tar -zxvf kibana-7.9.1-linux-x86_64.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重命名</span></span><br><span class="line">mv kibana-7.9.1-linux-x86_64 kibana</span><br></pre></td></tr></table></figure><p>然后在进入kibana目录，找到config文件夹下的kibana.yml进行配置的修改</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /soft/kibana/config/kibana.yml</span><br></pre></td></tr></table></figure><p>然后找到下面的内容</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#对外暴露服务的地址</span></span><br><span class="line">server.host: <span class="string">&quot;0.0.0.0&quot;</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">#配置Elasticsearch</span></span><br><span class="line">elasticsearch.url: <span class="string">&quot;http://127.0.0.1:9200&quot;</span></span><br></pre></td></tr></table></figure><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><p>修改配置完成后，我们就可以启动kibana了</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#启动</span></span><br><span class="line">./bin/kibana</span><br></pre></td></tr></table></figure><p>点击启动，发现报错了</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924195011533.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924195011533.png" alt="image-20200924195011533"></a></p><p>原因是kibana不能使用root用户进行启动，所以我们切换到elsearch用户</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 将soft文件夹的所属者改成elsearch</span></span><br><span class="line">chown elsearch:elsearch /soft/ -R</span><br><span class="line"></span><br><span class="line"><span class="comment"># 切换用户</span></span><br><span class="line">su elsearch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动</span></span><br><span class="line">./bin/kibana</span><br></pre></td></tr></table></figure><p>然后打开下面的地址，即可访问我们的kibana了</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://202.193.56.222:5601/</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924200502907.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924200502907.png" alt="image-20200924200502907"></a></p><h2 id="功能说明"><a href="#功能说明" class="headerlink" title="功能说明"></a>功能说明</h2><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924200615995.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924200615995.png" alt="image-20200924200615995"></a></p><ul><li>Discover：数据探索</li><li>Visualize：可视化</li><li>Dashboard：仪表盘</li><li>Timelion：时序控件</li><li>Canvas：画布</li><li>Machine Learning：机器学习</li><li>Infrastructure：基本信息</li><li>Logs：数据日志展示</li><li>APM：性能监控</li><li>Dev Tools：开发者工具</li><li>Monitoring：监控</li><li>Management：管理</li></ul><h2 id="数据探索"><a href="#数据探索" class="headerlink" title="数据探索"></a>数据探索</h2><p>先添加索引信息</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201110208.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201110208.png" alt="image-20200924201110208"></a></p><p>然后我们就输入匹配规则进行匹配</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201234997.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201234997.png" alt="image-20200924201234997"></a></p><p>然后选择时间字段，一般选择第一个</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201312845.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201312845.png" alt="image-20200924201312845"></a></p><p>索引创建完毕后</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201354838.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201354838.png" alt="image-20200924201354838"></a></p><p>然后我们就可以往nginx error.log日志文件中，添加几天错误记录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;hello error&quot;</span> &gt;&gt; error.log</span><br></pre></td></tr></table></figure><p>我们追加了两条数据，然后到kibana的discover中，刷新页面，就能够看到我们刚添加的日志了，同时我们点击右侧还可以选择需要展示的字段，非常的方便</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201952010.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924201952010.png" alt="image-20200924201952010"></a></p><p>点击右上角，我们还可以针对时间来进行过滤</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924202210114.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924202210114.png" alt="image-20200924202210114"></a></p><h2 id="Metricbeat仪表盘"><a href="#Metricbeat仪表盘" class="headerlink" title="Metricbeat仪表盘"></a>Metricbeat仪表盘</h2><p>现在将Metricbeat的数据展示在Kibana中，首先需要修改我们的MetricBeat配置</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#修改metricbeat配置</span></span><br><span class="line">setup.kibana:</span><br><span class="line">  host: <span class="string">&quot;192.168.40.133:5601&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#安装仪表盘到Kibana【需要确保Kibana在正常运行，这个过程可能会有些耗时】</span></span><br><span class="line">./metricbeat setup --dashboards</span><br></pre></td></tr></table></figure><p>安装完成后，如下所示</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924203831606.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924203831606.png" alt="image-20200924203831606"></a></p><p>然后我们启动Metricbeat</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.&#x2F;metricbeat -e</span><br></pre></td></tr></table></figure><p>然后到kibana页面下，找到我们刚刚安装的仪表盘</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924204708099.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924204708099.png" alt="image-20200924204708099"></a></p><p>然后我们就能够看到非常多的指标数据了</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924204636176.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924204636176.png" alt="image-20200924204636176"></a></p><h2 id="Nginx指标仪表盘【Metricbeat】"><a href="#Nginx指标仪表盘【Metricbeat】" class="headerlink" title="Nginx指标仪表盘【Metricbeat】"></a>Nginx指标仪表盘【Metricbeat】</h2><p>选择Metricbeat的nginx仪表盘即可</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924205523107.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924205523107.png" alt="image-20200924205523107"></a></p><p>然后就能够看到Nginx的指标信息了</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924205552446.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924205552446.png" alt="image-20200924205552446"></a></p><h2 id="Nginx日志仪表盘"><a href="#Nginx日志仪表盘" class="headerlink" title="Nginx日志仪表盘"></a>Nginx日志仪表盘</h2><p>我们可以和刚刚Metricbeat的仪表盘一样，也可以将filebeat收集的日志记录，推送到Kibana中</p><p>首先我们需要修改filebeat的 mogublog-nginx.yml配置文件</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">1</span></span><br><span class="line"><span class="attr">output.elasticsearch:</span></span><br><span class="line">  <span class="attr">hosts:</span> [<span class="string">&quot;127.0.0.1:9200&quot;</span>]</span><br><span class="line"><span class="attr">filebeat.config.modules:</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">$&#123;path.config&#125;/modules.d/*.yml</span></span><br><span class="line">  <span class="attr">reload.enabled:</span> <span class="literal">false</span></span><br><span class="line"><span class="attr">setup.kibana:</span></span><br><span class="line">  <span class="attr">host:</span> <span class="string">&quot;127.0.0.1:5601&quot;</span></span><br></pre></td></tr></table></figure><p>然后按照仪表盘</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./filebeat -c mogublog-nginx.yml setup</span><br></pre></td></tr></table></figure><p>等待一会后，仪表盘也安装成功了</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924210454873.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924210454873.png" alt="image-20200924210454873"></a></p><p>然后我们启动filebeat即可</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./filebeat -e -c mogublog-nginx.yml</span><br></pre></td></tr></table></figure><p>启动完成后，我们回到我们的Kibana中，找到Dashboard，添加我们的filebeat - nginx即可</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924210913557.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924210913557.png" alt="image-20200924210913557"></a></p><p>然后就能看到我们的仪表盘了，上图就是请求的来源</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924210816489.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924210816489.png" alt="image-20200924210816489"></a></p><blockquote><p>需要注意的是，这些仪表盘本身是没有的，我们需要通过filebeat来进行安装</p></blockquote><h2 id="Kibana自定义仪表盘"><a href="#Kibana自定义仪表盘" class="headerlink" title="Kibana自定义仪表盘"></a>Kibana自定义仪表盘</h2><p>在Kibana中，我们也可以自定义图标，如制作柱形图</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924211227780.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924211227780.png" alt="image-20200924211227780"></a></p><p>我们选择最下面的 Vertical Bar，也就是柱形图，然后在选择我们的索引</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924211318386.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924211318386.png" alt="image-20200924211318386"></a></p><p>这样就出来了</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924211427643.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924211427643.png" alt="image-20200924211427643"></a></p><h2 id="开发者工具"><a href="#开发者工具" class="headerlink" title="开发者工具"></a>开发者工具</h2><p>在Kibana中，为开发者的测试提供了便捷的工具使用，如下：</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924211727920.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924211727920.png" alt="image-20200924211727920"></a></p><p>我们就可以在这里面写一些请求了</p><p><a href="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924212137167.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/3_Kibana%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BB%8B%E7%BB%8D/images/image-20200924212137167.png" alt="image-20200924212137167"></a></p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> elk </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Logstash入门简介</title>
      <link href="operation/logstash/"/>
      <url>operation/logstash/</url>
      
        <content type="html"><![CDATA[<h1 id="Logstash入门简介"><a href="#Logstash入门简介" class="headerlink" title="Logstash入门简介"></a>Logstash入门简介</h1><h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p>Logstash是一个开源的服务器端数据处理管道，能够同时从多个来源采集数据，转换数据，然后将数据发送到最喜欢的存储库中（我们的存储库当然是ElasticSearch）</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924213006328.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924213006328.png" alt="image-20200924213006328"></a></p><p>我们回到我们ElasticStack的架构图，可以看到Logstash是充当数据处理的需求的，当我们的数据需要处理的时候，会将它发送到Logstash进行处理，否则直接送到ElasticSearch中</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924213319642.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924213319642.png" alt="image-20200924213319642"></a></p><h2 id="用途"><a href="#用途" class="headerlink" title="用途"></a>用途</h2><p>Logstash可以处理各种各样的输入，从文档，图表中=，数据库中，然后处理完后，发送到</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924213350345.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924213350345.png" alt="image-20200924213350345"></a></p><h2 id="部署安装"><a href="#部署安装" class="headerlink" title="部署安装"></a>部署安装</h2><p>Logstash主要是将数据源的数据进行一行一行的处理，同时还直接过滤切割等功能。</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924214152859.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924214152859.png" alt="image-20200924214152859"></a></p><p>首先到官网下载logstash：<a href="https://www.elastic.co/cn/downloads/logstash">https://www.elastic.co/cn/downloads/logstash</a></p><p>选择我们需要下载的版本：</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924215805219.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924215805219.png" alt="image-20200924215805219"></a></p><p>下载完成后，使用xftp工具，将其丢入到服务器中</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#检查jdk环境，要求jdk1.8+</span></span><br><span class="line">java -version</span><br><span class="line"></span><br><span class="line"><span class="comment">#解压安装包</span></span><br><span class="line">tar -xvf logstash-7.9.1.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="comment">#第一个logstash示例</span></span><br><span class="line">bin/logstash -e <span class="string">&#x27;input &#123; stdin &#123; &#125; &#125; output &#123; stdout &#123;&#125; &#125;&#x27;</span></span><br></pre></td></tr></table></figure><p>其实原来的logstash的作用，就是为了做数据的采集，但是因为logstash的速度比较慢，所以后面使用beats来代替了Logstash，当我们使用上面的命令进行启动的时候，就可以发现了，因为logstash使用java写的，首先需要启动虚拟机，最后下图就是启动完成的截图</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221006644.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221006644.png" alt="image-20200924221006644"></a></p><h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>我们在控制台输入 hello，马上就能看到它的输出信息</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221052791.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221052791.png" alt="image-20200924221052791"></a></p><h2 id="配置详解"><a href="#配置详解" class="headerlink" title="配置详解"></a>配置详解</h2><p>Logstash的配置有三部分，如下所示</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">input &#123; <span class="comment">#输入</span></span><br><span class="line">stdin &#123; ... &#125; <span class="comment">#标准输入</span></span><br><span class="line">&#125;</span><br><span class="line">filter &#123; <span class="comment">#过滤，对数据进行分割、截取等处理</span></span><br><span class="line">...</span><br><span class="line">&#125;</span><br><span class="line">output &#123; <span class="comment">#输出</span></span><br><span class="line">stdout &#123; ... &#125; <span class="comment">#标准输出</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="输入"><a href="#输入" class="headerlink" title="输入"></a>输入</h3><ul><li>采集各种样式、大小和来源的数据，数据往往以各种各样的形式，或分散或集中地存在于很多系统中。</li><li>Logstash 支持各种输入选择 ，可以在同一时间从众多常用来源捕捉事件。能够以连续的流式传输方式，轻松地从您的日志、指标、Web 应用、数据存储以及各种 AWS 服务采集数据。</li></ul><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221256569.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221256569.png" alt="image-20200924221256569"></a></p><h3 id="过滤"><a href="#过滤" class="headerlink" title="过滤"></a>过滤</h3><ul><li>实时解析和转换数据</li><li>数据从源传输到存储库的过程中，Logstash 过滤器能够解析各个事件，识别已命名的字段以构建结构，并将它们转换成通用格式，以便更轻松、更快速地分析和实现商业价值。</li></ul><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221459397.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221459397.png" alt="image-20200924221459397"></a></p><h3 id="输出"><a href="#输出" class="headerlink" title="输出"></a>输出</h3><p>Logstash 提供众多输出选择，您可以将数据发送到您要指定的地方，并且能够灵活地解锁众多下游用例。</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221528089.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924221528089.png" alt="image-20200924221528089"></a></p><h2 id="读取自定义日志"><a href="#读取自定义日志" class="headerlink" title="读取自定义日志"></a>读取自定义日志</h2><p>前面我们通过Filebeat读取了nginx的日志，如果是自定义结构的日志，就需要读取处理后才能使用，所以，这个时候就需要使用Logstash了，因为Logstash有着强大的处理能力，可以应对各种各样的场景。</p><h3 id="日志结构"><a href="#日志结构" class="headerlink" title="日志结构"></a>日志结构</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2019-03-15 21:21:21|ERROR|1 读取数据出错|参数：id=1002</span><br></pre></td></tr></table></figure><p>可以看到，日志中的内容是使用“|”进行分割的，使用，我们在处理的时候，也需要对数据做分割处理。</p><h3 id="编写配置文件"><a href="#编写配置文件" class="headerlink" title="编写配置文件"></a>编写配置文件</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim mogublog-pipeline.conf</span><br></pre></td></tr></table></figure><p>然后添加如下内容</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">input &#123;</span><br><span class="line">    file &#123;</span><br><span class="line">        path =&gt; <span class="string">&quot;/soft/beats/logs/app.log&quot;</span></span><br><span class="line">        start_position =&gt; <span class="string">&quot;beginning&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">filter &#123;</span><br><span class="line">    mutate &#123;</span><br><span class="line">        split =&gt; &#123;<span class="string">&quot;message&quot;</span>=&gt;<span class="string">&quot;|&quot;</span>&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">output &#123;</span><br><span class="line">    stdout &#123; codec =&gt; rubydebug &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>启动</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#启动</span></span><br><span class="line">./bin/logstash -f ./mogublog-pipeline.conf</span><br></pre></td></tr></table></figure><p>然后我们就插入我们的测试数据</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;2019-03-15 21:21:21|ERROR|读取数据出错|参数：id=1002&quot;</span> &gt;&gt; app.log</span><br></pre></td></tr></table></figure><p>然后我们就可以看到logstash就会捕获到刚刚我们插入的数据，同时我们的数据也被分割了</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924224710757.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924224710757.png" alt="image-20200924224710757"></a></p><h3 id="输出到Elasticsearch"><a href="#输出到Elasticsearch" class="headerlink" title="输出到Elasticsearch"></a>输出到Elasticsearch</h3><p>我们可以修改我们的配置文件，将我们的日志记录输出到ElasticSearch中</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">input &#123;</span><br><span class="line">    file &#123;</span><br><span class="line">        path =&gt; <span class="string">&quot;/soft/beats/logs/app.log&quot;</span></span><br><span class="line">        start_position =&gt; <span class="string">&quot;beginning&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">filter &#123;</span><br><span class="line">    mutate &#123;</span><br><span class="line">        split =&gt; &#123;<span class="string">&quot;message&quot;</span>=&gt;<span class="string">&quot;|&quot;</span>&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">output &#123;</span><br><span class="line">    elasticsearch &#123;</span><br><span class="line">        hosts =&gt; [<span class="string">&quot;127.0.0.1:9200&quot;</span>]</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后在重启我们的logstash</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./bin/logstash -f ./mogublog-pipeline.conf</span><br></pre></td></tr></table></figure><p>然后向日志记录中，插入两条数据</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;2019-03-15 21:21:21|ERROR|读取数据出错|参数：id=1002&quot;</span> &gt;&gt; app.log</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;2019-03-15 21:21:21|ERROR|读取数据出错|参数：id=1002&quot;</span> &gt;&gt; app.log</span><br></pre></td></tr></table></figure><p>最后就能够看到我们刚刚插入的数据了</p><p><a href="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924230314560.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/4_Logstash%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924230314560.png" alt="image-20200924230314560"></a></p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> elk </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Beats入门简介</title>
      <link href="unclass/beat/"/>
      <url>unclass/beat/</url>
      
        <content type="html"><![CDATA[<p>使用Beat收集nginx日志和指标数据</p><h2 id="项目需求"><a href="#项目需求" class="headerlink" title="项目需求"></a>项目需求</h2><p>Nginx是一款非常优秀的web服务器，往往nginx服务会作为项目的访问入口，那么，nginx的性能保障就变得非常重要了，如果nginx的运行出现了问题就会对项目有较大的影响，所以，我们需要对nginx的运行有监控措施，实时掌握nginx的运行情况，那就需要收集nginx的运行指标和分析nginx的运行日志了。</p><h2 id="业务流程"><a href="#业务流程" class="headerlink" title="业务流程"></a>业务流程</h2><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924081614472.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924081614472.png" alt="image-20200924081614472"></a></p><p>说明：</p><ul><li>通过Beats采集Nginx的指标数据和日志数据</li><li>Beats采集到数据后发送到Elasticsearch中</li><li>Kibana读取数据进行分析</li><li>用户通过Kibana进行查看分析报表</li></ul><h2 id="部署Nginx"><a href="#部署Nginx" class="headerlink" title="部署Nginx"></a>部署Nginx</h2><p>部署教程可以参考这篇博客：<a href="http://www.moguit.cn/#/info?blogUid=e8d3e38ba35b4765ae128256eb44e341">CentOS下如何安装Nginx？</a></p><p>部署完成后，我们就可以启动nginx了</p><p>启动完成后，我们通过下面命令，就可以获取到nginx中的内容了</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tail -f /var/<span class="built_in">log</span>/nginx/access.log</span><br></pre></td></tr></table></figure><h2 id="Beats简介"><a href="#Beats简介" class="headerlink" title="Beats简介"></a>Beats简介</h2><p>通过查看ElasticStack可以发现，Beats主要用于采集数据</p><p>官网地址：<a href="https://www.elastic.co/cn/beats/">https://www.elastic.co/cn/beats/</a></p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924091657242.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924091657242.png" alt="image-20200924091657242"></a></p><p>Beats平台其实是一个轻量性数据采集器，通过集合多种单一用途的采集器，从成百上千台机器中向Logstash或ElasticSearch中发送数据。</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924091716757.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924091716757.png" alt="image-20200924091716757"></a></p><p>通过Beats包含以下的数据采集功能</p><ul><li>Filebeat：采集日志文件</li><li>Metricbeat：采集指标</li><li>Packetbeat：采集网络数据</li></ul><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924092015934.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924092015934.png" alt="image-20200924092015934"></a></p><p>如果我们的数据不需要任何处理，那么就可以直接发送到ElasticSearch中</p><p>如果们的数据需要经过一些处理的话，那么就可以发送到Logstash中，然后处理完成后，在发送到ElasticSearch</p><p>最后在通过Kibana对我们的数据进行一系列的可视化展示</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924092348121.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924092348121.png" alt="image-20200924092348121"></a></p><h2 id="Filebeat"><a href="#Filebeat" class="headerlink" title="Filebeat"></a>Filebeat</h2><h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h3><p>Filebeat是一个轻量级的日志采集器</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924092551044.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924092551044.png" alt="image-20200924092551044"></a></p><h3 id="为什么要用Filebeat？"><a href="#为什么要用Filebeat？" class="headerlink" title="为什么要用Filebeat？"></a>为什么要用Filebeat？</h3><p>当你面对成百上千、甚至成千上万的服务器、虚拟机和溶气气生成的日志时，请告别SSH吧！Filebeat将为你提供一种轻量型方法，用于转发和汇总日志与文件，让简单的事情不再繁华，关于Filebeat的记住以下两点：</p><ul><li>轻量级日志采集器</li><li>输送至ElasticSearch或者Logstash，在Kibana中实现可视化</li></ul><h3 id="架构"><a href="#架构" class="headerlink" title="架构"></a>架构</h3><p>用于监控、收集服务器日志文件.</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924092749077.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924092749077.png" alt="image-20200924092749077"></a></p><p>流程如下：</p><ul><li>首先是input输入，我们可以指定多个数据输入源，然后通过通配符进行日志文件的匹配</li><li>匹配到日志后，就会使用Harvester（收割机），将日志源源不断的读取到来</li><li>然后收割机收割到的日志，就传递到Spooler（卷轴），然后卷轴就在将他们传到对应的地方</li></ul><h3 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h3><p>官网地址：<a href="https://www.elastic.co/cn/downloads/beats/filebeat">https://www.elastic.co/cn/downloads/beats/filebeat</a></p><p>选中对应版本的Filebeat，我这里是Centos部署的，所以下载Linux版本</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924093459418.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924093459418.png" alt="image-20200924093459418"></a></p><p>下载后，我们上传到服务器上，然后创建一个文件夹</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建文件夹</span></span><br><span class="line">mkdir -p /soft/beats</span><br><span class="line"><span class="comment"># 解压文件</span></span><br><span class="line">tar -zxvf filebeat-7.9.1-linux-x86_64.tar.gz </span><br><span class="line"><span class="comment"># 重命名</span></span><br><span class="line">mv filebeat-7.9.1-linux-x86_64/ filebeat</span><br></pre></td></tr></table></figure><p>然后我们进入到filebeat目录下，创建对应的配置文件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 进入文件夹</span></span><br><span class="line"><span class="built_in">cd</span> filebeats</span><br><span class="line"><span class="comment"># 创建配置文件</span></span><br><span class="line">vim mogublog.yml</span><br></pre></td></tr></table></figure><p>添加如下内容</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span> <span class="comment"># filebeat input输入</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">stdin</span>    <span class="comment"># 标准输入</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span>  <span class="comment"># 启用标准输入</span></span><br><span class="line"><span class="attr">setup.template.settings:</span> </span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">3</span> <span class="comment"># 指定下载数</span></span><br><span class="line"><span class="attr">output.console:</span>  <span class="comment"># 控制台输出</span></span><br><span class="line">  <span class="attr">pretty:</span> <span class="literal">true</span>   <span class="comment"># 启用美化功能</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><h3 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h3><p>在我们添加完配置文件后，我们就可以对filebeat进行启动了</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./filebeat -e -c mogublog.yml</span><br></pre></td></tr></table></figure><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924094825962.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924094825962.png" alt="image-20200924094825962"></a></p><p>然后我们在控制台输入hello，就能看到我们会有一个json的输出，是通过读取到我们控制台的内容后输出的</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924095032365.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924095032365.png" alt="image-20200924095032365"></a></p><p>内容如下</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">&quot;@timestamp&quot;</span>:<span class="string">&quot;2019-01-12T12:50:03.585Z&quot;</span>,</span><br><span class="line">    &quot;@metadata&quot;:&#123; #元数据信息</span><br><span class="line">        &quot;beat&quot;:&quot;filebeat&quot;,</span><br><span class="line">        &quot;type&quot;:&quot;doc&quot;,</span><br><span class="line">        &quot;version&quot;:&quot;6.5.4&quot;</span><br><span class="line">    &#125;,</span><br><span class="line">    &quot;source&quot;:&quot;&quot;,</span><br><span class="line">    &quot;offset&quot;:0,</span><br><span class="line">    &quot;message&quot;:&quot;hello&quot;, #元数据信息</span><br><span class="line">    &quot;prospector&quot;:&#123;</span><br><span class="line">        &quot;type&quot;:&quot;stdin&quot; #元数据信息</span><br><span class="line">    &#125;,</span><br><span class="line">    &quot;input&quot;:&#123; #控制台标准输入</span><br><span class="line">        &quot;type&quot;:&quot;stdin&quot;</span><br><span class="line">    &#125;,</span><br><span class="line">    &quot;beat&quot;:&#123;  #beat版本以及主机信息</span><br><span class="line">        &quot;name&quot;:&quot;itcast01&quot;,</span><br><span class="line">        &quot;hostname&quot;:&quot;ElasticStack&quot;,</span><br><span class="line">        &quot;version&quot;:&quot;6.5.4&quot;</span><br><span class="line">    &#125;,</span><br><span class="line">    &quot;host&quot;:&#123;</span><br><span class="line">        &quot;name&quot;:&quot;ElasticStack&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="读取文件"><a href="#读取文件" class="headerlink" title="读取文件"></a>读取文件</h3><p>我们需要再次创建一个文件，叫 mogublog-log.yml，然后在文件里添加如下内容</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">log</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">paths:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/soft/beats/logs/*.log</span></span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">3</span></span><br><span class="line"><span class="attr">output.console:</span></span><br><span class="line">  <span class="attr">pretty:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>添加完成后，我们在到下面目录创建一个日志文件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建文件夹</span></span><br><span class="line">mkdir -p /soft/beats/logs</span><br><span class="line"></span><br><span class="line"><span class="comment"># 进入文件夹</span></span><br><span class="line"><span class="built_in">cd</span> /soft/beats/logs</span><br><span class="line"></span><br><span class="line"><span class="comment"># 追加内容</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;hello&quot;</span> &gt;&gt; a.log</span><br></pre></td></tr></table></figure><p>然后我们再次启动filebeat</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./filebeat -e -c mogublog-log.yml</span><br></pre></td></tr></table></figure><p>能够发现，它已经成功加载到了我们的日志文件 a.log</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924095926036.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924095926036.png" alt="image-20200924095926036"></a></p><p>同时我们还可以继续往文件中追加内容</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;are you ok ?&quot;</span> &gt;&gt; a.log</span><br></pre></td></tr></table></figure><p>追加后，我们再次查看filebeat，也能看到刚刚我们追加的内容</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924102409656.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924102409656.png" alt="image-20200924102409656"></a></p><p>可以看出，已经检测到日志文件有更新，立刻就会读取到更新的内容，并且输出到控制台。</p><h3 id="自定义字段"><a href="#自定义字段" class="headerlink" title="自定义字段"></a>自定义字段</h3><p>但我们的元数据没办法支撑我们的业务时，我们还可以自定义添加一些字段</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">filebeat.inputs:</span><br><span class="line">- <span class="built_in">type</span>: <span class="built_in">log</span></span><br><span class="line">  enabled: <span class="literal">true</span></span><br><span class="line">  paths:</span><br><span class="line">    - /soft/beats/logs/*.<span class="built_in">log</span></span><br><span class="line">  tags: [<span class="string">&quot;web&quot;</span>, <span class="string">&quot;test&quot;</span>]  <span class="comment">#添加自定义tag，便于后续的处理</span></span><br><span class="line">  fields:  <span class="comment">#添加自定义字段</span></span><br><span class="line">    from: test-web</span><br><span class="line">  fields_under_root: <span class="literal">true</span> <span class="comment">#true为添加到根节点，false为添加到子节点中</span></span><br><span class="line">setup.template.settings:</span><br><span class="line">  index.number_of_shards: 3</span><br><span class="line">output.console:</span><br><span class="line">  pretty: <span class="literal">true</span></span><br><span class="line">  <span class="built_in">enable</span>: <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>添加完成后，我们重启 filebeat</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./filebeat -e -c mogublog-log.yml</span><br></pre></td></tr></table></figure><p>然后添加新的数据到 a.log中</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;test-web&quot;</span> &gt;&gt; a.log</span><br></pre></td></tr></table></figure><p>我们就可以看到字段在原来的基础上，增加了两个</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924103323033.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924103323033.png" alt="image-20200924103323033"></a></p><h3 id="输出到ElasticSearch"><a href="#输出到ElasticSearch" class="headerlink" title="输出到ElasticSearch"></a>输出到ElasticSearch</h3><p>我们可以通过配置，将修改成如下所示</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">log</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">paths:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/soft/beats/logs/*.log</span></span><br><span class="line">  <span class="attr">tags:</span> [<span class="string">&quot;web&quot;</span>, <span class="string">&quot;test&quot;</span>]</span><br><span class="line">  <span class="attr">fields:</span></span><br><span class="line">    <span class="attr">from:</span> <span class="string">test-web</span></span><br><span class="line">  <span class="attr">fields_under_root:</span> <span class="literal">false</span> </span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">1</span></span><br><span class="line"><span class="attr">output.elasticsearch:</span></span><br><span class="line">  <span class="attr">hosts:</span> [<span class="string">&quot;127.0.0.1:9200&quot;</span>]</span><br></pre></td></tr></table></figure><p>启动成功后，我们就能看到它已经成功连接到了es了</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924145624812.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924145624812.png" alt="image-20200924145624812"></a></p><p>然后我们到刚刚的 logs文件夹向 a.log文件中添加内容</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;hello mogublog&quot;</span> &gt;&gt; a.log</span><br></pre></td></tr></table></figure><p>在ES中，我们可以看到，多出了一个 filebeat的索引库</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924145928050.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924145928050.png" alt="image-20200924145928050"></a></p><p>然后我们浏览对应的数据，看看是否有插入的数据内容</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924150500441.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924150500441.png" alt="image-20200924150500441"></a></p><h3 id="Filebeat工作原理"><a href="#Filebeat工作原理" class="headerlink" title="Filebeat工作原理"></a>Filebeat工作原理</h3><p>Filebeat主要由下面几个组件组成： harvester、prospector 、input</p><h4 id="harvester"><a href="#harvester" class="headerlink" title="harvester"></a>harvester</h4><ul><li>负责读取单个文件的内容</li><li>harvester逐行读取每个文件（一行一行读取），并把这些内容发送到输出</li><li>每个文件启动一个harvester，并且harvester负责打开和关闭这些文件，这就意味着harvester运行时文件描述符保持着打开的状态。</li><li>在harvester正在读取文件内容的时候，文件被删除或者重命名了，那么Filebeat就会续读这个文件，这就会造成一个问题，就是只要负责这个文件的harvester没用关闭，那么磁盘空间就不会被释放，默认情况下，Filebeat保存问价你打开直到close_inactive到达</li></ul><h4 id="prospector"><a href="#prospector" class="headerlink" title="prospector"></a>prospector</h4><ul><li>prospector负责管理harvester并找到所有要读取的文件来源</li><li>如果输入类型为日志，则查找器将查找路径匹配的所有文件，并为每个文件启动一个harvester</li><li>Filebeat目前支持两种prospector类型：log和stdin</li><li>Filebeat如何保持文件的状态<ul><li>Filebeat保存每个文件的状态并经常将状态刷新到磁盘上的注册文件中</li><li>该状态用于记住harvester正在读取的最后偏移量，并确保发送所有日志行。</li><li>如果输出（例如ElasticSearch或Logstash）无法访问，Filebeat会跟踪最后发送的行，并在输出再次可以用时继续读取文件。</li><li>在Filebeat运行时，每个prospector内存中也会保存的文件状态信息，当重新启动Filebat时，将使用注册文件的数量来重建文件状态，Filebeat将每个harvester在从保存的最后偏移量继续读取</li><li>文件状态记录在data/registry文件中</li></ul></li></ul><h3 id="input"><a href="#input" class="headerlink" title="input"></a>input</h3><ul><li>一个input负责管理harvester，并找到所有要读取的源</li><li>如果input类型是log，则input查找驱动器上与已定义的glob路径匹配的所有文件，并为每个文件启动一个harvester</li><li>每个input都在自己的Go例程中运行</li><li>下面的例子配置Filebeat从所有匹配指定的glob模式的文件中读取行</li></ul><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">log</span></span><br><span class="line">  <span class="attr">paths:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/var/log/*.log</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/var/path2/*.log</span></span><br></pre></td></tr></table></figure><h3 id="启动命令"><a href="#启动命令" class="headerlink" title="启动命令"></a>启动命令</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">./filebeat -e -c mogublog-es.yml</span><br><span class="line">./filebeat -e -c mogublog-es.yml -d <span class="string">&quot;publish&quot;</span></span><br></pre></td></tr></table></figure><h3 id="参数说明"><a href="#参数说明" class="headerlink" title="参数说明"></a>参数说明</h3><ul><li><strong>-e：</strong>输出到标准输出，默认输出到syslog和logs下</li><li><strong>-c：</strong>指定配置文件</li><li><strong>-d：</strong>输出debug信息</li></ul><h3 id="读取Nginx中的配置文件"><a href="#读取Nginx中的配置文件" class="headerlink" title="读取Nginx中的配置文件"></a>读取Nginx中的配置文件</h3><p>我们需要创建一个 mogublog-nginx.yml配置文件</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">log</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">paths:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/soft/nginx/*.log</span></span><br><span class="line">  <span class="attr">tags:</span> [<span class="string">&quot;nginx&quot;</span>]</span><br><span class="line">  <span class="attr">fields_under_root:</span> <span class="literal">false</span> </span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">1</span></span><br><span class="line"><span class="attr">output.elasticsearch:</span></span><br><span class="line">  <span class="attr">hosts:</span> [<span class="string">&quot;127.0.0.1:9200&quot;</span>]</span><br></pre></td></tr></table></figure><p>启动后，可以在Elasticsearch中看到索引以及查看数据</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924161739842.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924161739842.png" alt="image-20200924161739842"></a></p><p>可以看到，在message中已经获取到了nginx的日志，但是，内容并没有经过处理，只是读取到原数据，那么对于我们后期的操作是不利的，有办法解决吗？</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924161814066.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924161814066.png" alt="image-20200924161814066"></a></p><h3 id="Module"><a href="#Module" class="headerlink" title="Module"></a>Module</h3><p>前面要想实现日志数据的读取以及处理都是自己手动配置的，其实，在Filebeat中，有大量的Module，可以简化我们的配置，直接就可以使用，如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./filebeat modules list</span><br></pre></td></tr></table></figure><p>得到的列表如下所示</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">Disabled:</span><br><span class="line">activemq</span><br><span class="line">apache</span><br><span class="line">auditd</span><br><span class="line">aws</span><br><span class="line">azure</span><br><span class="line">barracuda</span><br><span class="line">bluecoat</span><br><span class="line">cef</span><br><span class="line">checkpoint</span><br><span class="line">cisco</span><br><span class="line">coredns</span><br><span class="line">crowdstrike</span><br><span class="line">cylance</span><br><span class="line">elasticsearch</span><br><span class="line">envoyproxy</span><br><span class="line">f5</span><br><span class="line">fortinet</span><br><span class="line">googlecloud</span><br><span class="line">gsuite</span><br><span class="line">haproxy</span><br><span class="line">ibmmq</span><br><span class="line">icinga</span><br><span class="line">iis</span><br><span class="line">imperva</span><br><span class="line">infoblox</span><br><span class="line">iptables</span><br><span class="line">juniper</span><br><span class="line">kafka</span><br><span class="line">kibana</span><br><span class="line">logstash</span><br><span class="line">microsoft</span><br><span class="line">misp</span><br><span class="line">mongodb</span><br><span class="line">mssql</span><br><span class="line">mysql</span><br><span class="line">nats</span><br><span class="line">netflow</span><br><span class="line">netscout</span><br><span class="line">nginx</span><br><span class="line">o365</span><br><span class="line">okta</span><br><span class="line">osquery</span><br><span class="line">panw</span><br><span class="line">postgresql</span><br><span class="line">rabbitmq</span><br><span class="line">radware</span><br><span class="line">redis</span><br><span class="line">santa</span><br><span class="line">sonicwall</span><br><span class="line">sophos</span><br><span class="line">squid</span><br><span class="line">suricata</span><br><span class="line">system</span><br><span class="line">tomcat</span><br><span class="line">traefik</span><br><span class="line">zeek</span><br><span class="line">zscaler</span><br></pre></td></tr></table></figure><p>可以看到，内置了很多的module，但是都没有启用，如果需要启用需要进行enable操作：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#启动</span></span><br><span class="line">./filebeat modules <span class="built_in">enable</span> nginx </span><br><span class="line"><span class="comment">#禁用</span></span><br><span class="line">./filebeat modules <span class="built_in">disable</span> nginx</span><br></pre></td></tr></table></figure><p>可以发现，nginx的module已经被启用。</p><h4 id="nginx-module-配置"><a href="#nginx-module-配置" class="headerlink" title="nginx module 配置"></a>nginx module 配置</h4><p>我们到下面的目录，就能看到module的配置了</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 进入到module目录</span></span><br><span class="line"><span class="built_in">cd</span> modules.d/</span><br><span class="line"><span class="comment">#查看文件</span></span><br><span class="line">vim nginx.yml.disabled</span><br></pre></td></tr></table></figure><p>得到的文件内容如下所示</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Module: nginx</span></span><br><span class="line"><span class="comment"># Docs: https://www.elastic.co/guide/en/beats/filebeat/7.9/filebeat-module-nginx.html</span></span><br><span class="line"></span><br><span class="line">- module: nginx</span><br><span class="line">  <span class="comment"># Access logs</span></span><br><span class="line">  access:</span><br><span class="line">    enabled: <span class="literal">true</span></span><br><span class="line">    <span class="comment"># 添加日志文件</span></span><br><span class="line">    var.paths: [<span class="string">&quot;/var/log/nginx/access.log*&quot;</span>]</span><br><span class="line"></span><br><span class="line">    <span class="comment"># Set custom paths for the log files. If left empty,</span></span><br><span class="line">    <span class="comment"># Filebeat will choose the paths depending on your OS.</span></span><br><span class="line">    <span class="comment">#var.paths:</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># Error logs</span></span><br><span class="line">  error:</span><br><span class="line">    enabled: <span class="literal">true</span></span><br><span class="line">    var.paths: [<span class="string">&quot;/var/log/nginx/error.log*&quot;</span>]</span><br></pre></td></tr></table></figure><h4 id="配置filebeat"><a href="#配置filebeat" class="headerlink" title="配置filebeat"></a>配置filebeat</h4><p>我们需要修改刚刚的mogublog-nginx.yml文件，然后添加到我们的module</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">1</span></span><br><span class="line"><span class="attr">output.elasticsearch:</span></span><br><span class="line">  <span class="attr">hosts:</span> [<span class="string">&quot;127.0.0.1:9200&quot;</span>]</span><br><span class="line"><span class="attr">filebeat.config.modules:</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">$&#123;path.config&#125;/modules.d/*.yml</span></span><br><span class="line">  <span class="attr">reload.enabled:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure><h4 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h4><p>我们启动我们的filebeat</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./filebeat -e -c itcast-nginx.yml</span><br></pre></td></tr></table></figure><p>如果启动的时候发现出错了，错误如下所示，执行如图所示的脚本即可 【新版本的ES好像不会出现这个错误】</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#启动会出错，如下</span></span><br><span class="line">ERROR fileset/factory.go:142 Error loading pipeline: Error loading pipeline <span class="keyword">for</span></span><br><span class="line">fileset nginx/access: This module requires the following Elasticsearch plugins:</span><br><span class="line">ingest-user-agent, ingest-geoip. You can install them by running the following</span><br><span class="line">commands on all the Elasticsearch nodes:</span><br><span class="line">  sudo bin/elasticsearch-plugin install ingest-user-agent</span><br><span class="line">  sudo bin/elasticsearch-plugin install ingest-geoip</span><br></pre></td></tr></table></figure><p>启动成功后，能看到日志记录已经成功刷新进去了</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924164750123.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924164750123.png" alt="image-20200924164750123"></a></p><p>我们可以测试一下，刷新nginx页面，或者向错误日志中，插入数据</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;err&quot;</span> &gt;&gt; error.log</span><br></pre></td></tr></table></figure><p>能够看到，刚刚的记录已经成功插入了</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924164927557.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924164927557.png" alt="image-20200924164927557"></a></p><p>关于module的其它使用，可以参考文档：</p><p><a href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-modules.html">https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-modules.html</a></p><h2 id="Metricbeat"><a href="#Metricbeat" class="headerlink" title="Metricbeat"></a>Metricbeat</h2><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924170741928.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924170741928.png" alt="image-20200924170741928"></a></p><ul><li>定期收集操作系统或应用服务的指标数据</li><li>存储到Elasticsearch中，进行实时分析</li></ul><h3 id="Metricbeat组成"><a href="#Metricbeat组成" class="headerlink" title="Metricbeat组成"></a>Metricbeat组成</h3><p>Metricbeat有2部分组成，一部分是Module，另一个部分为Metricset</p><ul><li>Module<ul><li>收集的对象：如 MySQL、Redis、Nginx、操作系统等</li></ul></li><li>Metricset<ul><li>收集指标的集合：如 cpu、memory，network等</li></ul></li></ul><p>以Redis Module为例：</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924170958343.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924170958343.png" alt="image-20200924170958343"></a></p><h3 id="下载-1"><a href="#下载-1" class="headerlink" title="下载"></a>下载</h3><p>首先我们到<a href="https://www.elastic.co/cn/downloads/beats/metricbeat">官网</a>，找到Metricbeat进行下载</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924171232384.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924171232384.png" alt="image-20200924171232384"></a></p><p>下载完成后，我们通过xftp工具，移动到指定的目录下</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 移动到该目录下</span></span><br><span class="line"><span class="built_in">cd</span> /soft/beats</span><br><span class="line"><span class="comment"># 解压文件</span></span><br><span class="line">tar -zxvf </span><br><span class="line"><span class="comment"># 修改文件名</span></span><br><span class="line">mv  metricbeat</span><br></pre></td></tr></table></figure><p>然后修改配置文件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim metricbeat.yml</span><br></pre></td></tr></table></figure><p>添加如下内容</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">metricbeat.config.modules:</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">$&#123;path.config&#125;/modules.d/*.yml</span></span><br><span class="line">  <span class="attr">reload.enabled:</span> <span class="literal">false</span></span><br><span class="line"><span class="attr">setup.template.settings:</span></span><br><span class="line">  <span class="attr">index.number_of_shards:</span> <span class="number">1</span></span><br><span class="line">  <span class="attr">index.codec:</span> <span class="string">best_compression</span></span><br><span class="line"><span class="attr">setup.kibana:</span></span><br><span class="line"><span class="attr">output.elasticsearch:</span></span><br><span class="line">  <span class="attr">hosts:</span> [<span class="string">&quot;&quot;</span><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span><span class="string">:9200&quot;</span>]</span><br><span class="line"><span class="attr">processors:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">add_host_metadata:</span> <span class="string">~</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">add_cloud_metadata:</span> <span class="string">~</span></span><br></pre></td></tr></table></figure><p>默认会指定的配置文件，就是在</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$&#123;path.config&#125;</span>/modules.d/*.yml</span><br></pre></td></tr></table></figure><p>也就是 system.yml文件，我们也可以自行开启其它的收集</p><h3 id="启动-1"><a href="#启动-1" class="headerlink" title="启动"></a>启动</h3><p>在配置完成后，我们通过如下命令启动即可</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./metricbeat -e</span><br></pre></td></tr></table></figure><p>在ELasticsearch中可以看到，系统的一些指标数据已经写入进去了：</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924171839291.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924171839291.png" alt="image-20200924171839291"></a></p><h3 id="system-module配置"><a href="#system-module配置" class="headerlink" title="system module配置"></a>system module配置</h3><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">module:</span> <span class="string">system</span></span><br><span class="line">  <span class="attr">period:</span> <span class="string">10s</span>  <span class="comment"># 采集的频率，每10秒采集一次</span></span><br><span class="line">  <span class="attr">metricsets:</span>  <span class="comment"># 采集的内容</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">cpu</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">load</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">memory</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">network</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">process</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">process_summary</span></span><br></pre></td></tr></table></figure><h3 id="Metricbeat-Module"><a href="#Metricbeat-Module" class="headerlink" title="Metricbeat Module"></a>Metricbeat Module</h3><p>Metricbeat Module的用法和我们之前学的filebeat的用法差不多</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#查看列表</span></span><br><span class="line">./metricbeat modules list</span><br></pre></td></tr></table></figure><p>能够看到对应的列表</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">Enabled:</span><br><span class="line">system <span class="comment">#默认启用</span></span><br><span class="line"></span><br><span class="line">Disabled:</span><br><span class="line">aerospike</span><br><span class="line">apache</span><br><span class="line">ceph</span><br><span class="line">couchbase</span><br><span class="line">docker</span><br><span class="line">dropwizard</span><br><span class="line">elasticsearch</span><br><span class="line">envoyproxy</span><br><span class="line">etcd</span><br><span class="line">golang</span><br><span class="line">graphite</span><br><span class="line">haproxy</span><br><span class="line">http</span><br><span class="line">jolokia</span><br><span class="line">kafka</span><br><span class="line">kibana</span><br><span class="line">kubernetes</span><br><span class="line">kvm</span><br><span class="line">logstash</span><br><span class="line">memcached</span><br><span class="line">mongodb</span><br><span class="line">munin</span><br><span class="line">mysql</span><br><span class="line">nginx</span><br><span class="line">php_fpm</span><br><span class="line">postgresql</span><br><span class="line">prometheus</span><br><span class="line">rabbitmq</span><br><span class="line">redis</span><br><span class="line">traefik</span><br><span class="line">uwsgi</span><br><span class="line">vsphere</span><br><span class="line">windows</span><br></pre></td></tr></table></figure><h3 id="Nginx-Module"><a href="#Nginx-Module" class="headerlink" title="Nginx Module"></a>Nginx Module</h3><h4 id="开启Nginx-Module"><a href="#开启Nginx-Module" class="headerlink" title="开启Nginx Module"></a>开启Nginx Module</h4><p>在nginx中，需要开启状态查询，才能查询到指标数据。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#重新编译nginx</span></span><br><span class="line">./configure --prefix=/usr/<span class="built_in">local</span>/nginx --with-http_stub_status_module</span><br><span class="line">make</span><br><span class="line">make install</span><br><span class="line"></span><br><span class="line">./nginx -V <span class="comment">#查询版本信息</span></span><br><span class="line">nginx version: nginx/1.11.6</span><br><span class="line">built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC)</span><br><span class="line">configure arguments: --prefix=/usr/<span class="built_in">local</span>/nginx --with-http_stub_status_module</span><br><span class="line"></span><br><span class="line"><span class="comment">#配置nginx</span></span><br><span class="line">vim nginx.conf</span><br><span class="line">location /nginx-status &#123;</span><br><span class="line">    stub_status on;</span><br><span class="line">    access_log off;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启nginx</span></span><br><span class="line">./nginx -s reload</span><br></pre></td></tr></table></figure><p>测试</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924172317526.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924172317526.png" alt="image-20200924172317526"></a></p><p>结果说明：</p><ul><li>Active connections：正在处理的活动连接数</li><li>server accepts handled requests<ul><li>第一个 server 表示Nginx启动到现在共处理了9个连接</li><li>第二个 accepts 表示Nginx启动到现在共成功创建 9 次握手</li><li>第三个 handled requests 表示总共处理了 21 次请求</li><li>请求丢失数 = 握手数 - 连接数 ，可以看出目前为止没有丢失请求</li></ul></li><li>Reading: 0 Writing: 1 Waiting: 1<ul><li>Reading：Nginx 读取到客户端的 Header 信息数</li><li>Writing：Nginx 返回给客户端 Header 信息数</li><li>Waiting：Nginx 已经处理完正在等候下一次请求指令的驻留链接（开启keep-alive的情况下，这个值等于 Active - (Reading+Writing)）</li></ul></li></ul><h3 id="配置nginx-module"><a href="#配置nginx-module" class="headerlink" title="配置nginx module"></a>配置nginx module</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#启用redis module</span></span><br><span class="line">./metricbeat modules <span class="built_in">enable</span> nginx</span><br><span class="line"></span><br><span class="line"><span class="comment">#修改redis module配置</span></span><br><span class="line">vim modules.d/nginx.yml</span><br></pre></td></tr></table></figure><p>然后修改下面的信息</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Module: nginx</span></span><br><span class="line"><span class="comment"># Docs: https://www.elastic.co/guide/en/beats/metricbeat/6.5/metricbeat-modulenginx.</span></span><br><span class="line">html</span><br><span class="line">  - module: nginx</span><br><span class="line"><span class="comment">#metricsets:</span></span><br><span class="line"><span class="comment"># - stubstatus</span></span><br><span class="line">  period: 10s</span><br><span class="line"><span class="comment"># Nginx hosts</span></span><br><span class="line">  hosts: [<span class="string">&quot;http://127.0.0.1&quot;</span>]</span><br><span class="line"><span class="comment"># Path to server status. Default server-status</span></span><br><span class="line">  server_status_path: <span class="string">&quot;nginx-status&quot;</span></span><br><span class="line"><span class="comment">#username: &quot;user&quot;</span></span><br><span class="line"><span class="comment">#password: &quot;secret&quot;</span></span><br></pre></td></tr></table></figure><p>修改完成后，启动nginx</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#启动</span></span><br><span class="line">./metricbeat -e</span><br></pre></td></tr></table></figure><h3 id="测试-1"><a href="#测试-1" class="headerlink" title="测试"></a>测试</h3><p>我们能看到，我们的nginx数据已经成功的采集到我们的系统中了</p><p><a href="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924173058267.png"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/elk/2_Beats%E5%85%A5%E9%97%A8%E7%AE%80%E4%BB%8B/images/image-20200924173058267.png" alt="image-20200924173058267"></a></p><p>可以看到，nginx的指标数据已经写入到了Elasticsearch。</p><p>更多的Module使用参见官方文档：</p><p><a href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html">https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html</a></p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://www.cnblogs.com/cjsblog/p/9495024.html">Filebeat 模块与配置</a></p><p><a href="https://www.bilibili.com/video/BV1iJ411c7Az">Elastic Stack（ELK）从入门到实践</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> elk </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>面试官：String长度有限制吗？是多少？</title>
      <link href="cp/java/java-string/"/>
      <url>cp/java/java-string/</url>
      
        <content type="html"><![CDATA[<h1 id="面试官：String长度有限制吗？是多少？还好我看过"><a href="#面试官：String长度有限制吗？是多少？还好我看过" class="headerlink" title="面试官：String长度有限制吗？是多少？还好我看过"></a>面试官：String长度有限制吗？是多少？还好我看过</h1><p>GoKu编程2020-11-09 14:58:52</p><h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>话说Java中String是有长度限制的，听到这里很多人不禁要问，String还有长度限制？是的有，而且在JVM编译中还有规范，而且有的家人们在面试的时候也遇到了，本人就遇到过面试的时候问这个的，而且在之前开发的中也真实地遇到过这个String长度限制的场景（将某固定文件转码成Base64的形式用字符串存储，在运行时需要的时候在转回来，当时文件比较大），那这个规范限制到底是怎么样的，咱们话不多说先䁖䁖去。</p><h1 id="String"><a href="#String" class="headerlink" title="String"></a>String</h1><p>首先要知道String的长度限制我们就需要知道String是怎么存储字符串的，String其实是使用的一个char类型的数组来存储字符串中的字符的。</p><p><a href="http://victorfengming.gitee.io/interview/java/img/61047e80f96e4053bf76e3fa20da119a"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/61047e80f96e4053bf76e3fa20da119a" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>存储String的容器原来是它</p><p>那么String既然是数组存储那数组会有长度的限制吗？是的有限制，但是是在有先提条件下的，我们看看String中返回length的方法。</p><p><a href="http://victorfengming.gitee.io/interview/java/img/bbef09dbc5be4f77a98ce2b3e7d4d57a"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/bbef09dbc5be4f77a98ce2b3e7d4d57a" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>String类中的length方法</p><p>由此我们看到返回值类型是int类型，Java中定义数组是可以给数组指定长度的，当然不指定的话默认会根据数组元素来指定：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">int[] arr1 &#x3D; new int[10]; &#x2F;&#x2F; 定义一个长度为10的数组</span><br><span class="line">int[] arr2 &#x3D; &#123;1,2,3,4,5&#125;; &#x2F;&#x2F; 那么此时数组的长度为5</span><br></pre></td></tr></table></figure><p>整数在java中是有限制的，我们通过源码来看看int类型对应的包装类Integer可以看到，其长度最大限制为2^31 -1，那么说明了数组的长度是0~2^31-1，那么计算一下就是（2^31-1 = 2147483647 = 4GB）</p><p><a href="http://victorfengming.gitee.io/interview/java/img/ead13fe430e0448fba01eabccb5c1ba1"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/ead13fe430e0448fba01eabccb5c1ba1" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>Integer的取值范围</p><p>看到这我们尝试通过编码来验证一下上述观点。</p><p><a href="http://victorfengming.gitee.io/interview/java/img/2c1dbdbd6ca545ef846d7c16dc6898a3"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/2c1dbdbd6ca545ef846d7c16dc6898a3" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>以字面量形式定义字符串</p><p>以上是我通过定义字面量的形式构造的10万个字符的字符串，编译之后虚拟机提示报错，说我们的字符串长度过长，不是说好了可以存21亿个吗？为什么才10万个就报错了呢？</p><p>其实这里涉及到了JVM编译规范的限制了，其实JVM在编译时，如果我们将字符串定义成了字面量的形式，编译时JVM是会将其存放在常量池中，这时候JVM对这个常量池存储String类型做出了限制，接下来我们先看下手册是如何说的。</p><p><a href="http://victorfengming.gitee.io/interview/java/img/fe9405097bb444ab90d2e98b2486ed9b"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/fe9405097bb444ab90d2e98b2486ed9b" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>java虚拟机规范截图</p><p>常量池中，每个 cp_info 项的格式必须相同，它们都以一个表示 cp_info 类型的单字节 “tag”项开头。后面 info[]项的内容 由tag 的类型所决定。</p><p><a href="http://victorfengming.gitee.io/interview/java/img/0bed1041d7bc4b8697f9f422e22adedc"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/0bed1041d7bc4b8697f9f422e22adedc" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>java虚拟机规范手册常量类型表</p><p>我们可以看到 String类型的表示是 CONSTANT_String ，我们来看下CONSTANT_String具体是如何定义的。</p><p><a href="http://victorfengming.gitee.io/interview/java/img/1d1cb367fb7241079d820d3ab6a7e7db"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/1d1cb367fb7241079d820d3ab6a7e7db" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>这里定义的 u2 string_index 表示的是常量池的有效索引，其类型是CONSTANT_Utf8_info 结构体表示的，这里我们需要注意的是其中定义的length我们看下面这张图。</p><p><a href="http://victorfengming.gitee.io/interview/java/img/a2999446c01c42fbab09d71ae41004d7"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/a2999446c01c42fbab09d71ae41004d7" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>在class文件中u2表示的是无符号数占2个字节单位，我们知道1个字节占8位，2个字节就是16位 ，那么2个字节能表示的范围就是2^16- 1 = 65535 。范中class文件格式对u1、u2的定义的解释做了一下摘要：</p><blockquote><p>这里对java虚拟机规摘要部分 1、class文件中文件内容类型解释 定义一组私有数据类型来表示 Class 文件的内容，它们包括 u1，u2 和 u4，分别代 表了 1、2 和 4 个字节的无符号数。 每个 Class 文件都是由 8 字节为单位的字节流组成，所有的 16 位、32 位和 64 位长度的数 据将被构造成 2 个、4 个和 8 个 8 字节单位来表示。</p><p>2、程序异常处理的有效范围解释 start_pc 和 end_pc 两项的值表明了异常处理器在 code[]数组中的有效范围。 start_pc 必须是对当前 code[]数组中某一指令的操作码的有效索引，end_pc 要 么是对当前 code[]数组中某一指令的操作码的有效索引，要么等于 code_length 的值，即当前 code[]数组的长度。start_pc 的值必须比 end_pc 小。 当程序计数器在范围[start_pc, end_pc)内时，异常处理器就将生效。即设 x 为 异常句柄的有效范围内的值，x 满足：start_pc ≤ x &lt; end_pc。 实际上，end_pc 值本身不属于异常处理器的有效范围这点属于 Java 虚拟机历史上 的一个设计缺陷：如果 Java 虚拟机中的一个方法的 code 属性的长度刚好是 65535 个字节，并且以一个 1 个字节长度的指令结束，那么这条指令将不能被异常处理器 所处理。不过编译器可以通过限制任何方法、实例初始化方法或类初始化方法的 code[]数组最大长度为 65534，这样可以间接弥补这个 BUG。</p><p>注意：这里对个人认为比较重要的点做了标记，首先第一个加粗说白了就是说数组有效范围就是【0-65565】但是第二个加粗的地方又解释了，因为虚拟机还需要1个字节的指令作为结束，所以其实真正的有效范围是【0-65564】，这里要注意这里的范围仅限编译时期，如果你是运行时拼接的字符串是可以超出这个范围的。</p></blockquote><p>接下来我们通过一个小实验来测试一下我们构建一个长度为65534的字符串，看看是否就能编译通过。 首先通过一个for循环构建65534长度的字符串，在控制台打印后，我们通过自己度娘的一个在线字符统计工具计算了一下确实是65534个字符，如下：</p><p><a href="http://victorfengming.gitee.io/interview/java/img/b42b1374f4a8497fb8540e5646e4c673"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/b42b1374f4a8497fb8540e5646e4c673" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p><a href="http://victorfengming.gitee.io/interview/java/img/1286368ac1c849569588f57ef39f6d6c"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/1286368ac1c849569588f57ef39f6d6c" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p>然后我们将字符复制后以定义字面量的形式赋值给字符串，可以看到我们选择这些字符右下角显示的确实是65534，于是乎运行了一波，果然成功了。</p><p><a href="http://victorfengming.gitee.io/interview/java/img/806eea6784f94e54a373afb14ae524e2"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/806eea6784f94e54a373afb14ae524e2" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><p><a href="http://victorfengming.gitee.io/interview/java/img/f07502ced76c4fb8bd0c4e548d4ca377"><img src= "/img/loading.gif" data-lazy-src="http://victorfengming.gitee.io/interview/java/img/f07502ced76c4fb8bd0c4e548d4ca377" alt="面试官：String长度有限制吗？是多少？还好我看过"></a></p><h2 id="看到这里我们来总结一下："><a href="#看到这里我们来总结一下：" class="headerlink" title="看到这里我们来总结一下："></a>看到这里我们来总结一下：</h2><p>问：字符串有长度限制吗？是多少？</p><p>答：首先字符串的内容是由一个字符数组 char[] 来存储的，由于数组的长度及索引是整数，且String类中返回字符串长度的方法length() 的返回值也是int ，所以通过查看java源码中的类Integer我们可以看到Integer的最大范围是2^31 -1,由于数组是从0开始的，所以数组的最大长度可以使【0~2^31-1】通过计算是大概4GB。</p><p>但是通过翻阅java虚拟机手册对class文件格式的定义以及常量池中对String类型的结构体定义我们可以知道对于索引定义了u2，就是无符号占2个字节，2个字节可以表示的最大范围是2^16 -1 = 65535。 其实是65535，但是由于JVM需要1个字节表示结束指令，所以这个范围就为65534了。超出这个范围在编译时期是会报错的，但是运行时拼接或者赋值的话范围是在整形的最大范围。</p><p>解析到这里就告一段落了，如果觉得在下讲得对你有帮助的可以点一波关注，下方的小拇指点一波支持，如果发现有讲的不好的或者有什么遗漏的，欢迎评论区留言相互学习，进步，后期会不定期更新更多的技术编程相关的文章。</p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> interview </tag>
            
            <tag> java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java和Php比较</title>
      <link href="comic/php-vs-java/"/>
      <url>comic/php-vs-java/</url>
      
        <content type="html"><![CDATA[<p>这样从几个方面来看：</p><p><strong>一、运行机制：</strong></p><p>　　Java代码被编译成字节码后，会在虚拟机里由JIT进行二次编译成为本地码，据传言其执行速度可以和C++相媲美，经过我自己测试，用Java实现一个简单的Memcache协议的缓存服务器，在Java 1.6下运行，和memcache本身相比，同样数据量的存取时间比大概是3:2，虽然有差距，但是比想象的要好很多。Java 1.7在JIT方面做了大量的改进，性能比Java 1.6还要好。<br>　　PHP是直接对文本代码进行解释执行，即便有opcode缓存技术，仍然有不可逾越的性能鸿沟。PHP的opcode类似于java的class字节码，仍是解释执行。</p><p><strong>二、处理并发：</strong></p><p>　　Java在并发处理上采取单进程多线程的方式，web应用会随着web server的启动而启动，而来自web 浏览器的请求将被分配给线程池内的闲置线程处理，也就是说当有请求到达的时候，进程是准备好的，线程是准备好的，Java要做的仅仅是业务逻辑处理了。<br>　　PHP在并发处理上时采取多进程的方式，在web server里没有物理的web应用概念，每个请求都相当于一个独立的应用，而进程也随着请求的到达才启动，而随着请求的结束而消亡。在Fast CGI环境下，有类似于线程池的进程池技术，对性能提高有很大的帮助。然而一方面web server和Fast cgi通讯仍需要通过socket，多出了一定的IO损耗，另一方面进程池内的进程间也很难进行通讯，所以在并发处理上仍然无法和Java相比。</p><p><strong>三、数据库应用：</strong></p><p>　　Java可以采用数据库连接池技术，节省下数据库连接过程带来的时间损失。<br>　　PHP没有这个好处，原因来自上面的第二条。<br>在数据库接口上java有JDBC，PHP有PDO，这两个很类似。然而Java有非常多的ORM技术框架(如Hibernate)使数据库操作变得异常简单，而PHP的运行方式决定了它是ORM的禁区（当然也可以做ORM，只是做到什么程度是由你对ORM带来的性能损耗的忍受程度决定的）。</p><p>原因说的具体点，就是php无法保存全局变量，php类中虽然有static变量，但是这个变量在一次http请求结束后就会被从内存中删除掉，但是java的static变量是可以一直存在内存中。这样php就无法使用“池”这种技术，因为无法将池中的数据保存下来</p><p><strong>四、缓存技术</strong></p><p>　　Java是单进程，很多缓存可以直接在Java的heap中做，而无需借助外在的工具，当然也有很好的缓存框架，比如Ehcache，因为没有网络IO，所以性能非常高。<br>　　PHP多进程单线程决定了它只能借助外来的缓存服务器，比如Memcache.</p><p><strong>五、热部署</strong></p><p>　　Java的热部署能力很弱，如果希望修个BUG而不停服是很难做到的。<br>　　PHP天然热部署。</p><p><strong>六、开发成本</strong></p><p>　　一个好Java程序员所需的知识储备更多，开发、调试所需的周期较长，好点的web server也都是收费的。<br>　　PHP免费、web server也免费。</p><p><strong>七、安全性</strong></p><p>　　这个要看你怎么来定义安全性，如果是代码安全，java class反编译很容易，这点上来说两者差不多。<br>　　Java有安全配置机制可保证一些“非法操作”无法执行，这点上来说PHP较弱。<br>　　然而Java很容易因为一个BUG导致整个应用宕掉，PHP就安全的多。</p><p>其实要说起来Java的好处多多，然而仅仅最后三条就可以让决策者取PHP而弃Java.</p><p>来自： <a href="http://www.dewen.org/q/525">http://www.dewen.org/q/525</a></p><hr><p>我从JSP和PHP的底层运作、框架扩展两个方面来谈谈两者的优劣。</p><p>1.<strong>底层运作</strong>:PHP使用两层、JSP使用三层来处理用户的请求和回显。<br>　　<strong>PHP的两层</strong>:Web服务器软件(Apache、Nginx)-&gt;PHP Zend解析器解释脚本并回显。<br>　　<strong>JSP的三层</strong>:Web服务器软件(Apache、Nginx)-&gt;容器-&gt;Java虚拟机解析Servlet并回显。<br>　　“<strong>容器</strong>“是JSP中的一个重要概念，容器可以控制servlet的生命周期(实例化和回收servlet);支持多线程调用servlet并处理线程销毁;使用XML配置安全性，不用写死在servlet里，不用重新编译;把JSP代码翻译为Java代码。<br>　　PHP少了这个中间层，像多线程、安全性自然不如JSP。但PHP可以采用Opcode技术把脚本解析的结果缓到内存(比如使用APC、eAccelerator、XCache)，省略了由PHP脚本到Opcode解析过程。这样速度当然比“把JSP代码翻译为Java代码”再由Java虚拟机解释执行快。不过对于动态确定的内容无法使用Opcode缓存技术。</p><p>2.<strong>框架扩</strong>展：<br>　　PHP提供扩展，方便与其它语言相互调用(如C)，也有成熟的PECL扩展可用。<br>　　JSP支持多框架，如1)使用<strong>Hibernate</strong>做数据持久连接，这也是JSP操作数据库比PHP快好多倍的原因，其次JSP与DB的接口操作也方便。2)使用<strong>Spring</strong>调用JavaBean处理业务逻辑。且JSP有Java做后盾，可以调用很多J2EE成熟的库(如EJB)，而PHP是做不到的。</p><p>另外，向@毛杭军说的，”PHP开发的人已习惯用由JAVA发扬光大的一些优点”，PHP是面向过程的，所以开发快。而JSP有Java提供的诸多类库，是面向对象的，所以功能强，但开发慢。之前公司做大型XXX系统服务器网站，使用的是<strong>JSP+ Oracle</strong>数据库。淘宝网也使用的也是相同的架构。</p><hr><p>一、 语言比较</p><p>Php是解释执行的服务器脚本语言，首先php有简单容易上手的特点。语法和c语言比较象，所以学过c语言的程序员可以很快的熟悉php的开发。而java需要先学好java的语法和熟悉一些核心的类库，懂得面向对象的程序设计方法。所以java不如php好学。</p><p>Java首先要编译成字节码.class文件，然后在java虚拟机上解释执行。Java的web开发首先最容易想到的就是JSP（现在已经到JSP2.0），原来的java的web开发都是用servlet来实现的，用servlet来开发需要程序员在java的源文件中嵌入大量的html代码。所以后来就出现了JSP,JSP可以方便的嵌入到html文件当中，其实jsp文件在服务器上执行的时候首先会被应用服务器转换成servlet，然后再编译执行。Jsp可以通过servlet和JavaBean的支持产生强大的功能。JavaBean 是一种可复用的、跨平台的软件组件。使用javabean可以方便的实现java代码和html的分离，能够增强系统的功能和软件的复用性。</p><p>Java的web开发属于SUN公司定义的J2EE其中的规范。而且在J2EE中包括了java的web开发的所有方面，如：JSP、Servlet、JDBC、JNDI、JAVABEAN、EJB等等。J2EE就特别适合于做大型的企业级的应用。</p><p>二、 数据库访问比较</p><p>Java通过JDBC来访问数据库，通过不同的数据库厂商提供的数据库驱动方便地访问数据库。访问数据库的接口比较统一。</p><p>PHP对于不同的数据库采用不同的数据库访问接口，所以数据库访问代码的通用性不强。例如：用Java开发的web应用从MySQL数据库转到Oracle数据库只需要做很少的修改。而PHP则需要做大量的修改工作。</p><p>三、 系统设计架构比较</p><p>采用Java的web开发技术，需要使用的是面向对象的系统设计方法，而PHP还是采用面向过程的开发方法。所以用Java进行开发前期需要做大量的系统分析和设计的工作。</p><p>四、 跨平台性</p><p>Java和PHP都有很好的跨平台的特性。几乎都可以在不作任何修改的情况下运行在Linux或者Windows等不同的操作系统上。</p><p>五、 开发成本比较</p><p>PHP最经典的组合就是：PHP + MySQL + Apache。非常适合开发中小型的web应用，开发的速度比较快。而且所有的软件都是开源免费的，可以减少投入。</p><p>Java的web应用服务器有免费Tomcat、JBoss等，如果需要更好的商业化的服务有：Web Sphere和 Web logic。</p><p>六、 分布式多层架构比较</p><p>PHP只能实现简单的分布式两层或三层的架构，而JAVA在这方面就比较强大，可以实现多层的网络架构。数据库层（持久化层）、应用（业务）逻辑层、表示逻辑层彼此分开，而且现在不同的层都已经有一些成熟的开发框架的支持。例如Struts就是利用java的web开发技术实现了MVC的设计模式，而在业务逻辑层也有Spring框架，数据库持久化层有Hibernate等框架。这些框架可以方便开发者高效、合理、科学得架构多层的商业应用。</p><p>下面简要的说一下Struts，它实质上是在JSP Model2的基础上实现的一个MVC（Model、View、Controler）框架。JSP Model2体系结构是一种联合使用JSP 与Servlet 来提供动态内容的方法。在Struts框架中，模型由实现业务逻辑的JavaBean或EJB组件构成，控制器由Servlet实现的，视图由一组JSP文件组成。采用Struts可以明确角色的定义和开发者与网页设计者的分工。而且项目越复杂，其优势越明显。</p><p>七、 源代码安全</p><p>PHP开发的程序的源代码都是公开的，他人拿到php开发的程序后都可以进行修改。</p><p>Java开发的程序，最后用户拿到的是只是一些编译好的class类，无法看到完整的源代码，安全性高。</p><p>八、性能比较</p><p>有人做过试验，对这两种种语言分别做回圈性能测试及存取Oracle数据库测试。</p><p>在循环性能测试中，JSP只用了令人吃惊的四秒钟就结束了20000＊20000的回圈。而PHP测试的是2000＊2000循环（少一个数量级），却分别用了63秒。</p><p>数据库测试中，二者分别对 Oracle 8 进行 1000 次 Insert,Update,Select和Delete： JSP 需要 13 秒，PHP 需要 69 秒。</p><hr><p>这两种语言使用的场景不是很一样，php一般用来做内容管理系统、论坛（以上两项代表是康盛的产品）、博客（facebook）、社交（微博）。</p><p>java一般用做企业级的开发，这种开发的重点适应业务需求的变动性，而且业务的复杂度也比较高。如果性能要求高的，也是要首选java。</p><p>facebook、百度、新浪的访问量也很大，但是他们仅仅将php作为页面展示层。facebook使用了多种语言（php，c/c++,java,erlang等），他们的php直接编译成c++运行，php和各个语言之间使用shift框架进行通信。同时facebook使用大量的nosql。</p><p>新浪微博的php，估计也是使用他们自己的引擎，新浪有ACE，估计底层有一些C的扩展。同时他们还有自己的KVDB，来处理大数据。</p><p>百度底层的搜索算法层应该是C写的，牵扯到数据库处理层，估计是java或者c写的。<br>所以说如果使用php处理大数据的话，一般是大公司用，这时候php就退化为一个界面展示层。</p><p>java处理大数据，依靠他先天的优势，可以方便的使用连接池等技术，又有soa等成熟技术处理分布式的业务需求。这方便国内的代表肯定是淘宝、阿里巴巴。</p><p>转自：<a href="https://www.cnblogs.com/tlll/p/3422211.html">https://www.cnblogs.com/tlll/p/3422211.html</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>内存耗尽后Redis会发生什么</title>
      <link href="comic/redis-memoryover/"/>
      <url>comic/redis-memoryover/</url>
      
        <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>作为一台服务器来说，内存并不是无限的，所以总会存在内存耗尽的情况，那么当 <code>Redis</code> 服务器的内存耗尽后，如果继续执行请求命令，<code>Redis</code> 会如何处理呢？</p><h1 id="内存回收"><a href="#内存回收" class="headerlink" title="内存回收"></a>内存回收</h1><p>使用<code>Redis</code> 服务时，很多情况下某些键值对只会在特定的时间内有效，为了防止这种类型的数据一直占有内存，我们可以给键值对设置有效期。<code>Redis</code> 中可以通过 <code>4</code> 个独立的命令来给一个键设置过期时间：</p><ul><li><code>expire key ttl</code>：将 <code>key</code> 值的过期时间设置为 <code>ttl</code> <strong>秒</strong>。</li><li><code>pexpire key ttl</code>：将 <code>key</code> 值的过期时间设置为 <code>ttl</code> <strong>毫秒</strong>。</li><li><code>expireat key timestamp</code>：将 <code>key</code> 值的过期时间设置为指定的 <code>timestamp</code> <strong>秒数</strong>。</li><li><code>pexpireat key timestamp</code>：将 <code>key</code> 值的过期时间设置为指定的 <code>timestamp</code> <strong>毫秒数</strong>。</li></ul><p>PS：不管使用哪一个命令，最终 <code>Redis</code> 底层都是使用 <code>pexpireat</code> 命令来实现的。另外，<code>set</code> 等命令也可以设置 <code>key</code> 的同时加上过期时间，这样可以保证设值和设过期时间的原子性。</p><p>设置了有效期后，可以通过 <code>ttl</code> 和 <code>pttl</code> 两个命令来查询剩余过期时间（如果未设置过期时间则下面两个命令返回 <code>-1</code>，如果设置了一个非法的过期时间，则都返回 <code>-2</code>）：</p><ul><li><code>ttl key</code> 返回 <code>key</code> 剩余过期秒数。</li><li><code>pttl key</code> 返回 <code>key</code> 剩余过期的毫秒数。</li></ul><h2 id="过期策略"><a href="#过期策略" class="headerlink" title="过期策略"></a>过期策略</h2><p>如果将一个过期的键删除，我们一般都会有三种策略：</p><ul><li>定时删除：为每个键设置一个定时器，一旦过期时间到了，则将键删除。这种策略对内存很友好，但是对 <code>CPU</code> 不友好，因为每个定时器都会占用一定的 <code>CPU</code> 资源。</li><li>惰性删除：不管键有没有过期都不主动删除，等到每次去获取键时再判断是否过期，如果过期就删除该键，否则返回键对应的值。这种策略对内存不够友好，可能会浪费很多内存。</li><li>定期扫描：系统每隔一段时间就定期扫描一次，发现过期的键就进行删除。这种策略相对来说是上面两种策略的折中方案，需要注意的是这个定期的频率要结合实际情况掌控好，使用这种方案有一个缺陷就是可能会出现已经过期的键也被返回。</li></ul><p>在 <code>Redis</code> 当中，其选择的是策略 <code>2</code> 和策略 <code>3</code> 的综合使用。不过 <code>Redis</code> 的定期扫描只会扫描设置了过期时间的键，因为设置了过期时间的键 <code>Redis</code> 会单独存储，所以不会出现扫描所有键的情况：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">redisDb</span> &#123;</span></span><br><span class="line">    dict *dict; <span class="comment">//所有的键值对</span></span><br><span class="line">    dict *expires; <span class="comment">//设置了过期时间的键值对</span></span><br><span class="line">   dict *blocking_keys; <span class="comment">//被阻塞的key,如客户端执行BLPOP等阻塞指令时</span></span><br><span class="line">   dict *watched_keys; <span class="comment">//WATCHED keys</span></span><br><span class="line">   <span class="keyword">int</span> id; <span class="comment">//Database ID</span></span><br><span class="line">   <span class="comment">//... 省略了其他属性</span></span><br><span class="line">&#125; redisDb;</span><br></pre></td></tr></table></figure><h2 id="8-种淘汰策略"><a href="#8-种淘汰策略" class="headerlink" title="8 种淘汰策略"></a>8 种淘汰策略</h2><p>假如 <code>Redis</code> 当中所有的键都没有过期，而且此时内存满了，那么客户端继续执行 <code>set</code> 等命令时 <code>Redis</code> 会怎么处理呢？<code>Redis</code> 当中提供了不同的淘汰策略来处理这种场景。</p><p>首先 <code>Redis</code> 提供了一个参数 <code>maxmemory</code> 来配置 <code>Redis</code> 最大使用内存：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">maxmemory &lt;bytes&gt;</span><br></pre></td></tr></table></figure><p>或者也可以通过命令 <code>config set maxmemory 1GB</code> 来动态修改。</p><p>如果没有设置该参数，那么在 <code>32</code> 位的操作系统中 <code>Redis</code> 最多使用 <code>3GB</code> 内存，而在 <code>64</code> 位的操作系统中则不作限制。</p><p><code>Redis</code> 中提供了 <code>8</code> 种淘汰策略，可以通过参数 <code>maxmemory-policy</code> 进行配置：</p><table><thead><tr><th>淘汰策略</th><th>说明</th></tr></thead><tbody><tr><td>volatile-lru</td><td>根据 LRU 算法删除设置了过期时间的键，直到腾出可用空间。如果没有可删除的键对象，且内存还是不够用时，则报错</td></tr><tr><td>allkeys-lru</td><td>根据 LRU 算法删除所有的键，直到腾出可用空间。如果没有可删除的键对象，且内存还是不够用时，则报错</td></tr><tr><td>volatile-lfu</td><td>根据 LFU 算法删除设置了过期时间的键，直到腾出可用空间。如果没有可删除的键对象，且内存还是不够用时，则报错</td></tr><tr><td>allkeys-lfu</td><td>根据 LFU 算法删除所有的键，直到腾出可用空间。如果没有可删除的键对象，且内存还是不够用时，则报错</td></tr><tr><td>volatile-random</td><td>随机删除设置了过期时间的键，直到腾出可用空间。如果没有可删除的键对象，且内存还是不够用时，则报错</td></tr><tr><td>allkeys-random</td><td>随机删除所有键，直到腾出可用空间。如果没有可删除的键对象，且内存还是不够用时，则报错</td></tr><tr><td>volatile-ttl</td><td>根据键值对象的 ttl 属性， 删除最近将要过期数据。 如果没有，则直接报错</td></tr><tr><td>noeviction</td><td>默认策略，不作任何处理，直接报错</td></tr></tbody></table><p>PS：淘汰策略也可以直接使用命令 <code>config set maxmemory-policy &lt;策略&gt;</code> 来进行动态配置。</p><h2 id="LRU-算法"><a href="#LRU-算法" class="headerlink" title="LRU 算法"></a>LRU 算法</h2><p><code>LRU</code> 全称为：<code>Least Recently Used</code>。即：最近最长时间未被使用。这个主要针对的是使用时间。</p><h3 id="Redis-改进后的-LRU-算法"><a href="#Redis-改进后的-LRU-算法" class="headerlink" title="Redis 改进后的 LRU 算法"></a>Redis 改进后的 LRU 算法</h3><p>在 <code>Redis</code> 当中，并没有采用传统的 <code>LRU</code> 算法，因为传统的 <code>LRU</code> 算法存在 <code>2</code> 个问题：</p><ul><li>需要额外的空间进行存储。</li><li>可能存在某些 <code>key</code> 值使用很频繁，但是最近没被使用，从而被 <code>LRU</code> 算法删除。</li></ul><p>为了避免以上 <code>2</code> 个问题，<code>Redis</code> 当中对传统的 <code>LRU</code> 算法进行了改造，<strong>通过抽样的方式进行删除</strong>。</p><p>配置文件中提供了一个属性 <code>maxmemory_samples 5</code>，默认值就是 <code>5</code>，表示随机抽取 <code>5</code> 个 <code>key</code> 值，然后对这 <code>5</code> 个 <code>key</code> 值按照 <code>LRU</code> 算法进行删除，所以很明显，<code>key</code> 值越大，删除的准确度越高。</p><p>对抽样 <code>LRU</code> 算法和传统的 <code>LRU</code> 算法，<code>Redis</code> 官网当中有一个对比图：</p><ul><li>浅灰色带是被删除的对象。</li><li>灰色带是未被删除的对象。</li><li>绿色是添加的对象。</li></ul><p><img src= "/img/loading.gif" data-lazy-src="2232223-20210215094536691-559224923.png" alt="img"></p><p>左上角第一幅图代表的是传统 <code>LRU</code> 算法，可以看到，当抽样数达到 <code>10</code> 个（右上角），已经和传统的 <code>LRU</code> 算法非常接近了。</p><h3 id="Redis-如何管理热度数据"><a href="#Redis-如何管理热度数据" class="headerlink" title="Redis 如何管理热度数据"></a>Redis 如何管理热度数据</h3><p>前面我们讲述字符串对象时，提到了 <code>redisObject</code> 对象中存在一个 <code>lru</code> 属性：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">redisObject</span> &#123;</span></span><br><span class="line">    <span class="keyword">unsigned</span> type:<span class="number">4</span>;<span class="comment">//对象类型（4位=0.5字节）</span></span><br><span class="line">    <span class="keyword">unsigned</span> encoding:<span class="number">4</span>;<span class="comment">//编码（4位=0.5字节）</span></span><br><span class="line">    <span class="keyword">unsigned</span> lru:LRU_BITS;<span class="comment">//记录对象最后一次被应用程序访问的时间（24位=3字节）</span></span><br><span class="line">    <span class="keyword">int</span> refcount;<span class="comment">//引用计数。等于0时表示可以被垃圾回收（32位=4字节）</span></span><br><span class="line">    <span class="keyword">void</span> *ptr;<span class="comment">//指向底层实际的数据存储结构，如：SDS等(8字节)</span></span><br><span class="line">&#125; robj;</span><br></pre></td></tr></table></figure><p><code>lru</code> 属性是创建对象的时候写入，对象被访问到时也会进行更新。正常人的思路就是最后决定要不要删除某一个键肯定是用当前时间戳减去 <code>lru</code>，差值最大的就优先被删除。但是 <code>Redis</code> 里面并不是这么做的，<code>Redis</code> 中维护了一个全局属性 <code>lru_clock</code>，这个属性是通过一个全局函数 <code>serverCron</code> 每隔 <code>100</code> 毫秒执行一次来更新的，记录的是当前 <code>unix</code> 时间戳。</p><p>最后决定删除的数据是通过 <code>lru_clock</code> 减去对象的 <code>lru</code> 属性而得出的。那么为什么 <code>Redis</code> 要这么做呢？直接取全局时间不是更准确吗？</p><p>这是因为这么做可以避免每次更新对象的 <code>lru</code> 属性的时候可以直接取全局属性，而不需要去调用系统函数来获取系统时间，从而提升效率（<code>Redis</code> 当中有很多这种细节考虑来提升性能，可以说是对性能尽可能的优化到极致）。</p><p>不过这里还有一个问题，我们看到，<code>redisObject</code> 对象中的 <code>lru</code> 属性只有 <code>24</code> 位，<code>24</code> 位只能存储 <code>194</code> 天的时间戳大小，一旦超过 <code>194</code> 天之后就会重新从 <code>0</code> 开始计算，所以这时候就可能会出现 <code>redisObject</code> 对象中的 <code>lru</code> 属性大于全局的 <code>lru_clock</code> 属性的情况。</p><p>正因为如此，所以计算的时候也需要分为 <code>2</code> 种情况：</p><ul><li>当全局 <code>lruclock</code> &gt; <code>lru</code>，则使用 <code>lruclock</code> - <code>lru</code> 得到空闲时间。</li><li>当全局 <code>lruclock</code> &lt; <code>lru</code>，则使用 <code>lruclock_max</code>（即 <code>194</code> 天） - <code>lru</code> + <code>lruclock</code> 得到空闲时间。</li></ul><p>需要注意的是，这种计算方式并不能保证抽样的数据中一定能删除空闲时间最长的。这是因为首先超过 <code>194</code> 天还不被使用的情况很少，再次只有 <code>lruclock</code> 第 <code>2</code> 轮继续超过 <code>lru</code> 属性时，计算才会出问题。</p><p>比如对象 <code>A</code> 记录的 <code>lru</code> 是 <code>1</code> 天，而 <code>lruclock</code> 第二轮都到 <code>10</code> 天了，这时候就会导致计算结果只有 <code>10-1=9</code> 天，实际上应该是 <code>194+10-1=203</code> 天。但是这种情况可以说又是更少发生，所以说这种处理方式是可能存在删除不准确的情况，但是本身这种算法就是一种近似的算法，所以并不会有太大影响。</p><h2 id="LFU-算法"><a href="#LFU-算法" class="headerlink" title="LFU 算法"></a>LFU 算法</h2><p><code>LFU</code> 全称为：<code>Least Frequently Used</code>。即：最近最少频率使用，这个主要针对的是使用频率。这个属性也是记录在<code>redisObject</code> 中的 <code>lru</code> 属性内。</p><p>当我们采用 <code>LFU</code> 回收策略时，<code>lru</code> 属性的高 <code>16</code> 位用来记录访问时间（last decrement time：ldt，单位为分钟），低 <code>8</code> 位用来记录访问频率（logistic counter：logc），简称 <code>counter</code>。</p><h3 id="访问频次递增"><a href="#访问频次递增" class="headerlink" title="访问频次递增"></a>访问频次递增</h3><p><code>LFU</code> 计数器每个键只有 <code>8</code> 位，它能表示的最大值是 <code>255</code>，所以 <code>Redis</code> 使用的是一种基于概率的对数器来实现 <code>counter</code> 的递增。r</p><p>给定一个旧的访问频次，当一个键被访问时，<code>counter</code> 按以下方式递增：</p><ol><li>提取 <code>0</code> 和 <code>1</code> 之间的随机数 <code>R</code>。</li><li><code>counter</code> - 初始值（默认为 <code>5</code>），得到一个基础差值，如果这个差值小于 <code>0</code>，则直接取 <code>0</code>，为了方便计算，把这个差值记为 <code>baseval</code>。</li><li>概率 <code>P</code> 计算公式为：<code>1/(baseval * lfu_log_factor + 1)</code>。</li><li>如果 <code>R &lt; P</code> 时，频次进行递增（<code>counter++</code>）。</li></ol><p>公式中的 <code>lfu_log_factor</code> 称之为对数因子，默认是 <code>10</code> ，可以通过参数来进行控制：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lfu_log_factor <span class="number">10</span></span><br></pre></td></tr></table></figure><p>下图就是对数因子 <code>lfu_log_factor</code> 和频次 <code>counter</code> 增长的关系图：</p><p><img src= "/img/loading.gif" data-lazy-src="2232223-20210215094631450-531937582.png" alt="img"></p><p>可以看到，当对数因子 <code>lfu_log_factor</code> 为 <code>100</code> 时，大概是 <code>10M（1000万）</code> 次访问才会将访问 <code>counter</code> 增长到 <code>255</code>，而默认的 <code>10</code> 也能支持到 <code>1M（100万）</code> 次访问 <code>counter</code> 才能达到 <code>255</code> 上限，这在大部分场景都是足够满足需求的。</p><h3 id="访问频次递减"><a href="#访问频次递减" class="headerlink" title="访问频次递减"></a>访问频次递减</h3><p>如果访问频次 <code>counter</code> 只是一直在递增，那么迟早会全部都到 <code>255</code>，也就是说 <code>counter</code> 一直递增不能完全反应一个 <code>key</code> 的热度的，所以当某一个 <code>key</code> 一段时间不被访问之后，<code>counter</code> 也需要对应减少。</p><p><code>counter</code> 的减少速度由参数 <code>lfu-decay-time</code> 进行控制，默认是 <code>1</code>，单位是分钟。默认值 <code>1</code> 表示：<code>N</code> 分钟内没有访问，<code>counter</code> 就要减 <code>N</code>。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lfu-decay-time <span class="number">1</span></span><br></pre></td></tr></table></figure><p>具体算法如下：</p><ol><li>获取当前时间戳，转化为<strong>分钟</strong>后取低 <code>16</code> 位（为了方便后续计算，这个值记为 <code>now</code>）。</li><li>取出对象内的 <code>lru</code> 属性中的高 <code>16</code> 位（为了方便后续计算，这个值记为 <code>ldt</code>）。</li><li>当 <code>lru</code> &gt; <code>now</code> 时，默认为过了一个周期（<code>16</code> 位，最大 <code>65535</code>)，则取差值 <code>65535-ldt+now</code>：当 <code>lru</code> &lt;= <code>now</code> 时，取差值 <code>now-ldt</code>（为了方便后续计算，这个差值记为 <code>idle_time</code>）。</li><li>取出配置文件中的 <code>lfu_decay_time</code> 值，然后计算：<code>idle_time / lfu_decay_time</code>（为了方便后续计算，这个值记为<code>num_periods</code>）。</li><li>最后将<code>counter</code>减少：<code>counter - num_periods</code>。</li></ol><p>看起来这么复杂，其实计算公式就是一句话：取出当前的时间戳和对象中的 <code>lru</code> 属性进行对比，计算出当前多久没有被访问到，比如计算得到的结果是 <code>100</code> 分钟没有被访问，然后再去除配置参数 <code>lfu_decay_time</code>，如果这个配置默认为 <code>1</code>也即是 <code>100/1=100</code>，代表 <code>100</code> 分钟没访问，所以 <code>counter</code> 就减少 <code>100</code>。</p><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>本文主要介绍了 <code>Redis</code> 过期键的处理策略，以及当服务器内存不够时 <code>Redis</code> 的 <code>8</code> 种淘汰策略，最后介绍了 <code>Redis</code> 中的两种主要的淘汰算法 <code>LRU</code> 和 <code>LFU</code>。</p>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java虚拟机</title>
      <link href="unclass/about_jvm/"/>
      <url>unclass/about_jvm/</url>
      
        <content type="html"><![CDATA[<p>JVM是Java Virtual Machine（Java虚拟机）的缩写，JVM是一种用于计算设备的规范，它是一个虚构出来的计算机，是通过在实际的计算机上仿真模拟各种计算机功能来实现的。</p><script>window.location.href='http://victorfengming.gitee.io/about_jvm/';</script>]]></content>
      
      
      
        <tags>
            
            <tag> summer </tag>
            
            <tag> java </tag>
            
            <tag> jvm </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Gitbook文档索引</title>
      <link href="index/gitbook/"/>
      <url>index/gitbook/</url>
      
        <content type="html"><![CDATA[<blockquote><p>Created by <a href="https://www.gitbook.com/">gitbook</a></p></blockquote><h2 id="脚本"><a href="#脚本" class="headerlink" title="脚本"></a>脚本</h2><div>    <table>        <thead>        <tr>            <th></th>            <th></th>            <th></th>        </tr>        </thead>        <tbody>        <tr>            <td>                <a href="https://victorfengming.gitee.io/shell/">                    <span>shell</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/makefile/">                    <span>makefile</span>                </a>            </td>            <td></td>        </tr>        </tbody>    </table></div><h2 id="前端"><a href="#前端" class="headerlink" title="前端"></a>前端</h2><div>    <table>        <thead>        <tr>            <th></th>            <th></th>            <th></th>        </tr>        </thead>        <tbody>        <tr>            <td>                <a href="https://victorfengming.gitee.io/course/front_page/index.html">                    <span>html</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/network/">                    <span>network</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/typescript/">                    <span>typescript</span>                </a>            </td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/axios/">                    <span>axios</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/webpack/">                    <span>webpack</span>                </a>            </td>            <td></td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/vue/">                    <span>vue</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/react/">                    <span>react</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/promise/">                    <span>promise</span>                </a>            </td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/course/pyqt5/index.html">                    <span>pyqt5</span>                </a>            </td>            <td></td>            <td></td>        </tr>        </tbody>    </table></div><h2 id="后端"><a href="#后端" class="headerlink" title="后端"></a>后端</h2><div>    <table>        <thead>        <tr>            <th></th>            <th></th>            <th></th>        </tr>        </thead>        <tbody>        <tr>            <td>                <a href="https://victorfengming.gitee.io/scala/">                    <span>scala</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/python_book/index.html">                    <span>python</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/go/index.html">                    <span>golang</span>                </a>            </td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/go-camp/">                    <span>go-camp</span>                </a>            </td>        </tr>        </tbody>    </table></div><h2 id="框架"><a href="#框架" class="headerlink" title="框架"></a>框架</h2><div>    <table>        <thead>        <tr>            <th></th>            <th></th>            <th></th>        </tr>        </thead>        <tbody>        <tr>            <td>                <a href="https://victorfengming.gitee.io/course/beego/index.html">                    <span>beego</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/django/index.html">                    <span>django</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/flask/index.html">                    <span>flask</span>                </a>            </td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/springboot/">                    <span>springboot</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/springcloud/">                    <span>springcloud</span>                </a>            </td>            <td></td>        </tr>        </tbody>    </table></div><h2 id="数据库"><a href="#数据库" class="headerlink" title="数据库"></a>数据库</h2><div>    <table>        <thead>        <tr>            <th></th>            <th></th>            <th></th>            <th></th>        </tr>        </thead>        <tbody>        <tr>            <td>                <a href="https://victorfengming.gitee.io/course/mysql/index.html">                    <span>mysql</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/mybatis/index.html">                    <span>mybatis</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/nosql/index.html">                    <span>nosql</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/redis/index.html">                    <span>redis</span>                </a>            </td>        </tr>        </tbody>    </table></div><h2 id="大数据运维"><a href="#大数据运维" class="headerlink" title="大数据运维"></a>大数据运维</h2><div>    <table>        <thead>        <tr>            <th></th>            <th></th>            <th></th>            <th></th>        </tr>        </thead>        <tbody>        <tr>            <td>                <a href="https://victorfengming.gitee.io/shell/">                    <span>shell</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/docker/">                    <span>docker</span>                </a>            </td>            <td>            </td>            <td>                <a href="https://victorfengming.gitee.io/elk/">                    <span>elk</span>                </a>            </td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/flink/">                    <span>flink</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/hadoop/">                    <span>hadoop</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/hive/">                    <span>hive</span>                </a>            </td>            <td>                <a href="http://victorfengming.gitee.io/jenkins/">                    <span>jenkins</span>                </a>            </td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/kubernetes/">                    <span>kubernetes</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/zookeeper/">                    <span>zookeeper</span>                </a>            </td>            <td></td>            <td></td>        </tr>        </tbody>    </table></div><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><div>    <table>        <thead>        <tr>            <th></th>            <th></th>            <th></th>            <th></th>        </tr>        </thead>        <tbody>        <tr>            <td>                <a href="https://victorfengming.gitee.io/jvm/">                    <span>jvm</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/data_algorithm/">                    <span>data_algorithm</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/data_science/index.html">                    <span>data_science</span>                </a>            </td>            <td></td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/design_pattern/">                    <span>design_pattern</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/git/index.html">                    <span>git</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/course/svn/index.html">                    <span>svn</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/interview/">                    <span>interview</span>                </a>            </td>        </tr>        <tr>            <td>                <a href="https://victorfengming.gitee.io/rabbit_mq/">                    <span>rabbit_mq</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/leetcode/">                    <span>leetcode</span>                </a>            </td>            <td>                <a href="https://victorfengming.gitee.io/javase/">                    <span>javase</span>                </a>            </td>        </tr>        </tbody>    </table></div><style>    span:hover {        color: #FFFFFF;        background: #00b5e5;    }</style>]]></content>
      
      
      
        <tags>
            
            <tag> gitbook </tag>
            
            <tag> index </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>文件索引</title>
      <link href="index/file/"/>
      <url>index/file/</url>
      
        <content type="html"><![CDATA[<h2 id="classware"><a href="#classware" class="headerlink" title="classware"></a>classware</h2><ul><li><p><a href="https://victorfengming.gitee.io/file/pdf/axios.pdf">axios</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/data_algorithm.pdf">data_algorithm</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/java_about.pdf">java_about</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/java_design_pattern.pdf">java_design_pattern</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/java_interview_1.pdf">java_interview_1</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/kuang_redis.pdf">kuang_redis</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/scala.pdf">scala</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/sgg_MyBatis.pdf">sgg_MyBatis</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/sgg_Nginx.pdf">sgg_Nginx</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/sgg_Redis.pdf">sgg_Redis</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/juc/sgg_juc.pdf">sgg_Juc</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/sgg_regex.pdf">sgg_regex</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/rabbitmq/sgg_rabbitmq.pdf">sgg_rabbitmq</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/sgg_shell.pdf">sgg_shell</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/sgg_Spring.pdf">sgg_Spring</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/sgg_SpringMVC.pdf">sgg_SpringMVC</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/sgg_ZooKeeper.pdf">sgg_ZooKeeper</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/elk/sgg_elasticsearch.pdf">sgg_elasticsearch</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/webpack_1.pdf">webpack_1</a></p></li><li><p><a href="">_hadoop</a></p><ul><li><a href="https://victorfengming.gitee.io/file/pdf/hadoop/01_hadoop_start.pdf">01_hadoop_start</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/hadoop/02_hadoop_intro.pdf">02_hadoop_intro</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/hadoop/03_hadoop_hdfs.pdf">03_hadoop_hdfs</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/hadoop/04_hadoop_MapReduce.pdf">04_hadoop_MapReduce</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/hadoop/05_hadoop_Yarn.pdf">05_hadoop_Yarn</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/hadoop/06_hadoop_manual.pdf">06_hadoop_manual</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/hadoop/07_hadoop_source.pdf">07_hadoop_source</a></li></ul></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/Linux%E5%91%BD%E4%BB%A4%E8%A1%8C%E4%B8%8Eshell%E8%84%9A%E6%9C%AC%E7%BC%96%E7%A8%8B%E5%A4%A7%E5%85%A8_%E7%AC%AC3%E7%89%88_%E5%B8%83%E9%B2%81%E5%A7%86_P606.pdf">Linux命令行与shell脚本编程大全_第3版_布鲁姆_P606</a></p></li><li><p><a href="https://victorfengming.gitee.io/file/pdf/alibaba_architecture_design.pdf">alibaba_architecture_design</a><br>-<a href="https://victorfengming.gitee.io/file/pdf/mysql/high_performanc_mysql.pdf">high_performanc_mysql</a></p></li></ul><h2 id="interview"><a href="#interview" class="headerlink" title="interview"></a>interview</h2><h3 id="ApacheDubbo"><a href="#ApacheDubbo" class="headerlink" title="ApacheDubbo"></a>ApacheDubbo</h3><ul><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ApacheDubbo/dubbo%E6%9C%8D%E5%8A%A1%E7%9B%B8%E5%85%B3%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">dubbo服务相关面试题</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ApacheDubbo/%E7%AE%80%E8%BF%B0dubbo%E7%9A%84spi%E6%80%9D%E6%83%B3.pdf">简述dubbo的spi思想</a><h3 id="CAS"><a href="#CAS" class="headerlink" title="CAS"></a>CAS</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/CAS/%E8%B0%88%E4%B8%80%E8%B0%88%E5%AF%B9CAS%E7%9A%84%E7%90%86%E8%A7%A3.pdf">谈一谈对CAS的理解</a><h3 id="container"><a href="#container" class="headerlink" title="container"></a>container</h3><h3 id="data-algorithm"><a href="#data-algorithm" class="headerlink" title="data_algorithm"></a>data_algorithm</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/HashMap%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E7%BA%BF%E7%A8%8B%E4%B8%8D%E5%AE%89%E5%85%A8.pdf">HashMap为什么是线程不安全</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98.pdf">八皇后问题</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E5%A6%82%E4%BD%95%E8%A1%A1%E9%87%8F%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E7%9A%84%E6%95%88%E7%8E%87%EF%BC%9F.pdf">如何衡量程序运行的效率？</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">快速排序算法面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E6%89%BE%E5%87%BA%E4%B8%8D%E9%87%8D%E5%A4%8D%E7%9A%84%E6%95%B4%E6%95%B0.pdf">找出不重复的整数</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/data_algorithm/%E6%B1%82%E4%B8%AD%E4%BD%8D%E6%95%B0.pdf">求中位数</a><h3 id="design-pattern"><a href="#design-pattern" class="headerlink" title="design_pattern"></a>design_pattern</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/design_pattern/DDD%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">DDD面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/design_pattern/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">代理模式面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/design_pattern/%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BA%86%E8%A7%A3%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E5%90%97.pdf">你真的了解单例模式吗</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/design_pattern/%E7%A9%BA%E5%AF%B9%E8%B1%A1%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.pdf">空对象设计模式</a><h3 id="distributed-theory"><a href="#distributed-theory" class="headerlink" title="distributed_theory"></a>distributed_theory</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E4%BB%80%E4%B9%88%E6%98%AF%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9_%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%AA%E5%B4%A9%E7%9A%84%E5%9C%BA%E6%99%AF%E4%B8%8E%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.pdf">什么是缓存雪崩_服务器雪崩的场景与解决方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E4%BB%8E%E5%8D%95%E4%BD%93%E6%9E%B6%E6%9E%84_%E5%88%B0SOA_%E5%86%8D%E5%88%B0%E5%BE%AE%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E8%AF%A6%E8%A7%A3.pdf">从单体架构_到SOA_再到微服务的架构设计详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8FSession%E5%85%B1%E4%BA%AB%E7%9A%844%E7%B1%BB%E6%8A%80%E6%9C%AF%E6%96%B9%E6%A1%88_%E4%B8%8E%E4%BC%98%E5%8A%A3%E5%8A%BF%E6%AF%94%E8%BE%83.pdf">分布式Session共享的4类技术方案_与优劣势比较</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">分布式事务面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7%E7%9A%84%E5%8E%9F%E7%90%86%E4%B8%8E%E6%8A%80%E6%9C%AF%E5%AE%9E%E7%8E%B0%E6%96%B9%E6%A1%88.pdf">分布式数据库数据一致性的原理与技术实现方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8F%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%B9%82%E7%AD%89%E6%80%A7%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">分布式服务接口的幂等性面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E7%9A%84%E5%87%A0%E7%A7%8D%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F.pdf">分布式锁的几种实现方式</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/distributed_theory/%E8%B0%88%E8%B0%88%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%9B%B8%E5%85%B3%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%E4%B8%8E%E5%AE%9E%E6%88%98%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.pdf">谈谈分布式事务相关的一致性与实战解决方案</a><h3 id="docker"><a href="#docker" class="headerlink" title="docker"></a>docker</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/docker/%E8%AF%B4%E4%B8%80%E4%B8%8B%E4%BD%A0%E5%AF%B9docker%E7%9A%84%E4%BA%86%E8%A7%A3.pdf">说一下你对docker的了解</a><h3 id="ES"><a href="#ES" class="headerlink" title="ES"></a>ES</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ES/es%E5%9C%A8%E6%95%B0%E6%8D%AE%E9%87%8F%E5%BE%88%E5%A4%A7%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B_%E6%95%B0%E5%8D%81%E4%BA%BF%E7%BA%A7%E5%88%AB_%E5%A6%82%E4%BD%95%E6%8F%90%E9%AB%98%E6%9F%A5%E8%AF%A2%E6%95%88%E7%8E%87.pdf">es在数据量很大的情况下_数十亿级别_如何提高查询效率</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ES/ES%E7%9A%84%E6%95%B0%E6%8D%AE%E8%AF%BB%E5%8F%96%E8%BF%87%E7%A8%8B%E4%BB%A5%E5%8F%8A%E6%96%87%E6%A1%A3%E8%AF%BB%E5%86%99%E5%8E%9F%E7%90%86%E5%A4%A7%E8%87%B4%E5%88%86%E6%9E%90%E4%B8%80%E4%B8%8B.pdf">ES的数据读取过程以及文档读写原理大致分析一下</a><h3 id="HashMap"><a href="#HashMap" class="headerlink" title="HashMap"></a>HashMap</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/HashMap/HashMap%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86.pdf">HashMap底层原理</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/HashMap/Hash%E5%86%B2%E7%AA%81%E6%9C%89%E4%BB%80%E4%B9%88%E8%A7%A3%E5%86%B3%E6%96%B9%E5%BC%8F.pdf">Hash冲突有什么解决方式</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/HashMap/%E9%9D%A2%E8%AF%95%E9%A2%98-HashMap.pdf">面试题-HashMap</a><h3 id="IO"><a href="#IO" class="headerlink" title="IO"></a>IO</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/IO/JavaIO%E6%B5%81%E9%9D%A2%E8%AF%95.pdf">JavaIO流面试</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/IO/%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E9%9B%B6%E6%8B%B7%E8%B4%9D.pdf">如何实现零拷贝</a><h3 id="JDK"><a href="#JDK" class="headerlink" title="JDK"></a>JDK</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JDK/%E5%8F%8D%E5%B0%84%E7%9B%B8%E5%85%B3%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">反射相关面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JDK/%E8%AE%B2%E4%B8%80%E4%B8%8BJDK1.8%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">讲一下JDK1.8的新特性面试题解析</a><h3 id="Jsp"><a href="#Jsp" class="headerlink" title="Jsp"></a>Jsp</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Jsp/JSP%E4%B8%8ESevlet%E5%8C%BA%E5%88%AB_Jsp%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1_Jsp%E5%9B%9B%E7%A7%8D%E4%BD%9C%E7%94%A8%E5%9F%9F_session%E4%B8%8Ecookie%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">JSP与Sevlet区别_Jsp内置对象_Jsp四种作用域_session与cookie的区别</a><h3 id="JVM"><a href="#JVM" class="headerlink" title="JVM"></a>JVM</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/7%E7%A7%8DJVM%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E7%89%B9%E7%82%B9_%E4%BC%98%E5%8A%A3%E5%8A%BF_%E5%8F%8A%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">7种JVM垃圾收集器特点_优劣势_及使用场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/java%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96_%E6%9C%89%E5%93%AA%E4%BA%9B%E8%A1%A1%E9%87%8F%E6%8C%87%E6%A0%87_%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E4%BB%80%E4%B9%88_.pdf">java性能优化_有哪些衡量指标_需要注意什么_</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/JVM%E5%86%85%E5%AD%98%E8%B0%83%E4%BC%98.pdf">JVM内存调优</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/JVM%E7%9A%844%E7%A7%8D%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95_%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E6%80%BB%E7%BB%93.pdf">JVM的4种垃圾回收算法_垃圾回收机制与总结</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/Jvm%E7%BB%84%E6%88%90%E8%BF%90%E8%A1%8C%E6%97%B6%E5%8C%BA%E5%A0%86%E6%A0%88%E9%98%9F%E5%88%97%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">Jvm组成运行时区堆栈队列的区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/JVM/%E6%B7%B1%E5%85%A5%E8%AF%A6%E8%A7%A3JVM%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B%E4%B8%8EJVM%E5%8F%82%E6%95%B0%E8%AF%A6%E7%BB%86%E9%85%8D%E7%BD%AE.pdf">深入详解JVM内存模型与JVM参数详细配置</a><h3 id="Kafka"><a href="#Kafka" class="headerlink" title="Kafka"></a>Kafka</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Kafka/Kafka%E9%9D%A2%E8%AF%95%E9%A2%98Kafka%E9%80%9F%E5%BA%A6%E4%B8%BA%E4%BB%80%E4%B9%88%E5%BF%AB.pdf">Kafka面试题Kafka速度为什么快</a><h3 id="Lambda"><a href="#Lambda" class="headerlink" title="Lambda"></a>Lambda</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Lambda/Java8_Lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F.pdf">Java8_Lambda表达式</a><h3 id="leetcode"><a href="#leetcode" class="headerlink" title="leetcode"></a>leetcode</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/leetcode/%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E6%8D%A2%E6%95%B4%E6%95%B0.pdf">字符串转换整数</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/leetcode/%E6%95%B0%E7%BB%84%E4%B8%AD%E5%87%BA%E7%8E%B0%E6%AC%A1%E6%95%B0%E8%B6%85%E8%BF%87%E4%B8%80%E5%8D%8A%E7%9A%84%E6%95%B0%E5%AD%97.pdf">数组中出现次数超过一半的数字</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/leetcode/%E7%94%A8%E4%B8%A4%E4%B8%AA%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97.pdf">用两个栈实现队列</a><h3 id="load-balance"><a href="#load-balance" class="headerlink" title="load_balance"></a>load_balance</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/load_balance/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%9A%84%E5%8E%9F%E7%90%86_%E5%88%86%E7%B1%BB_%E5%AE%9E%E7%8E%B0%E6%9E%B6%E6%9E%84_%E4%BB%A5%E5%8F%8A%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">负载均衡的原理_分类_实现架构_以及使用场景</a><h3 id="MyBatis"><a href="#MyBatis" class="headerlink" title="MyBatis"></a>MyBatis</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/Mybatis%E4%B8%8EHibernate%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">Mybatis与Hibernate的区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/MyBatis%E4%B8%ADMapper%E6%8E%A5%E5%8F%A3%E7%9B%B8%E5%85%B3%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">MyBatis中Mapper接口相关面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/MyBatis%E5%8A%A8%E6%80%81sql%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">MyBatis动态sql面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/Mybatis%E5%BB%B6%E8%BF%9F%E5%8A%A0%E8%BD%BD.pdf">Mybatis延迟加载</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/MyBatis%E7%9A%84%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E5%92%8C%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98.pdf">MyBatis的一级缓存和二级缓存</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/%E4%BD%A0%E7%9F%A5%E9%81%93MyBatis%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%E4%B9%8B%E5%88%9D%E5%A7%8B%E5%8C%96%E6%98%AF%E5%A6%82%E4%BD%95%E6%89%A7%E8%A1%8C%E7%9A%84%E5%90%97.pdf">你知道MyBatis执行过程之初始化是如何执行的吗</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MyBatis/%E5%AF%B9MybatisPlugin%E7%9A%84%E4%BA%86%E8%A7%A3.pdf">对MybatisPlugin的了解</a><h3 id="MySQL-adv"><a href="#MySQL-adv" class="headerlink" title="MySQL_adv"></a>MySQL_adv</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MySQL_adv/mysql_B+%E6%A0%91%E7%B4%A2%E5%BC%95%E5%92%8C%E5%93%88%E5%B8%8C%E7%B4%A2%E5%BC%95%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">mysql_B+树索引和哈希索引的区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MySQL_adv/MySQL%E4%BA%8B%E5%8A%A1%E4%B8%8EMVCC%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E7%9A%84%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB.pdf">MySQL事务与MVCC如何实现的隔离级别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MySQL_adv/%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8+%E5%8A%A8%E6%80%81%E6%95%B0%E6%8D%AE%E6%BA%90+%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB.pdf">如何实现分库分表+动态数据源+读写分离</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/MySQL_adv/%E8%AE%BE%E8%AE%A1%E9%AB%98%E5%B9%B6%E5%8F%91%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%97%B6%E5%80%99_%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B1%82%E9%9D%A2%E8%AF%A5%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1.pdf">设计高并发系统的时候_数据库层面该如何设计</a><h3 id="Mysql-base"><a href="#Mysql-base" class="headerlink" title="Mysql_base"></a>Mysql_base</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Mysql_base/%E5%85%B3%E4%BA%8Emysql%E7%9A%84%E4%B8%89%E8%8C%83%E5%BC%8F_ACID_%E7%B4%A2%E5%BC%95%E7%9A%84%E5%AE%9E%E7%8E%B0.pdf">关于mysql的三范式_ACID_索引的实现</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/mysql/MySQL_Study_Log.pdf">MySQL_Study_Log</a></li></ul><h3 id="net"><a href="#net" class="headerlink" title="net"></a>net</h3><ul><li><a href="http://victorfengming.gitee.io/file/pdf/inter/net/TCP&UDP%E5%8C%BA%E5%88%AB_TCP%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E7%9B%AE%E7%9A%84_OSI%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8B_get%E5%92%8Cpost%E5%8C%BA%E5%88%AB.pdf">TCP&amp;UDP区别_TCP三次握手目的_OSI七层模型_get和post区别</a><h3 id="Netty"><a href="#Netty" class="headerlink" title="Netty"></a>Netty</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Netty/Netty%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86_%E7%89%B9%E7%82%B9%E4%B8%8E%E4%BC%98%E5%8A%BF_%E4%BB%A5%E5%8F%8A%E9%80%82%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">Netty的实现原理_特点与优势_以及适用场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Netty/NIO_BIO_AIO%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">NIO_BIO_AIO的区别</a><h3 id="Nginx"><a href="#Nginx" class="headerlink" title="Nginx"></a>Nginx</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Nginx/%E8%81%8A%E8%81%8A%E4%BD%A0%E5%AF%B9NGINX%E7%9A%84%E7%90%86%E8%A7%A3.pdf">聊聊你对NGINX的理解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Nginx/%E8%AF%B4%E4%B8%80%E4%B8%8B%E4%BD%A0%E5%AF%B9Nginx%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E4%B8%8E%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E7%90%86%E8%A7%A3.pdf">说一下你对Nginx正向代理与反向代理理解</a><h3 id="parallel-programming"><a href="#parallel-programming" class="headerlink" title="parallel_programming"></a>parallel_programming</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/4%E7%A7%8D%E5%B8%B8%E7%94%A8Java%E7%BA%BF%E7%A8%8B%E9%94%81%E7%9A%84%E7%89%B9%E7%82%B9_%E6%80%A7%E8%83%BD%E6%AF%94%E8%BE%83_%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">4种常用Java线程锁的特点_性能比较_使用场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/Java%E6%8F%90%E4%BE%9B%E4%BA%86%E5%93%AA%E5%87%A0%E7%A7%8D%E7%BA%BF%E7%A8%8B%E6%B1%A0_%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">Java提供了哪几种线程池_面试题</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/ThreadLocal%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E7%9A%84%E5%8E%9F%E5%9B%A0%E5%88%86%E6%9E%90%E4%BB%A5%E5%8F%8A%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D.pdf">ThreadLocal的内存泄露的原因分析以及如何避免</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/Volatile%E4%B8%8D%E4%BF%9D%E8%AF%81%E5%8E%9F%E5%AD%90%E6%80%A7%E5%8F%8A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.pdf">Volatile不保证原子性及解决方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/volatile%E5%8F%AF%E8%A7%81%E6%80%A7%E8%AF%A6%E8%A7%A3.pdf">volatile可见性详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/Volatile%E7%A6%81%E6%AD%A2%E6%8C%87%E4%BB%A4%E9%87%8D%E6%8E%92.pdf">Volatile禁止指令重排</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E4%BD%A0%E4%BA%86%E8%A7%A3Java%E5%B9%B6%E5%8F%91%E4%B9%8BAQS.pdf">你了解Java并发之AQS</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E4%BD%A0%E7%9F%A5%E9%81%93Java%E4%B8%AD%E6%9C%89%E5%93%AA%E4%BA%9B%E9%94%81.pdf">你知道Java中有哪些锁</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E4%BD%A0%E7%9F%A5%E9%81%93ReentrantLock%E5%90%97_%E8%B0%88%E4%B8%80%E8%B0%88%E5%AF%B9%E5%AE%83%E7%9A%84%E7%90%86%E8%A7%A3.pdf">你知道ReentrantLock吗_谈一谈对它的理解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%E4%B8%80%E4%B8%AA%E9%AB%98%E5%B9%B6%E5%8F%91%E7%B3%BB%E7%BB%9F.pdf">如何设计一个高并发系统</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E5%B9%B6%E5%8F%91%E5%AE%B9%E5%99%A8%E7%9A%84%E5%8E%9F%E7%90%86.pdf">并发容器的原理</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%81%8A%E4%B8%80%E8%81%8AJava%E5%B9%B6%E5%8F%91%E4%B9%8BSynchronized.pdf">让我们聊一聊Java并发之Synchronized</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/parallel_programming/%E8%B0%88%E4%B8%80%E8%B0%88%E5%B9%B6%E5%8F%91CAS_CompareAndSwap%E5%AE%9E%E7%8E%B0.pdf">谈一谈并发CAS_CompareAndSwap实现</a><h3 id="RabbitMQ"><a href="#RabbitMQ" class="headerlink" title="RabbitMQ"></a>RabbitMQ</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/RabbitMq%E9%98%B2%E6%AD%A2%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">RabbitMq防止消息丢失面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/Rabbit%E6%80%8E%E4%B9%88%E5%AF%B9%E6%B6%88%E6%81%AF%E7%A1%AE%E8%AE%A4%E6%9C%BA%E5%88%B6%E7%9A%84.pdf">Rabbit怎么对消息确认机制的</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%BF%E7%94%A8%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97.pdf">为什么使用消息队列</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/%E4%BB%80%E4%B9%88%E6%98%AF%E6%B5%81%E9%87%8F%E5%89%8A%E5%B3%B0_%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%E7%A7%92%E6%9D%80%E4%B8%9A%E5%8A%A1%E7%9A%84%E5%89%8A%E5%B3%B0%E5%9C%BA%E6%99%AF.pdf">什么是流量削峰_如何解决秒杀业务的削峰场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E6%B6%88%E6%81%AF%E7%9A%84%E9%A1%BA%E5%BA%8F%E6%80%A7.pdf">如何保证消息的顺序性</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RabbitMQ/%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%9A%84%E9%AB%98%E5%8F%AF%E7%94%A8.pdf">如何保证消息队列的高可用</a><h3 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis_RDB%E6%8C%81%E4%B9%85%E5%8C%96_AOF%E6%8C%81%E4%B9%85%E5%8C%96.pdf">Redis_RDB持久化_AOF持久化</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E5%8D%95%E7%BA%BF%E7%A8%8B_%E5%8F%8A%E9%AB%98%E5%B9%B6%E5%8F%91%E5%BF%AB%E7%9A%84%E5%8E%9F%E5%9B%A0.pdf">Redis为什么是单线程_及高并发快的原因</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E5%93%A8%E5%85%B5_%E5%A4%8D%E5%88%B6_%E9%9B%86%E7%BE%A4%E7%9A%84%E8%AE%BE%E8%AE%A1%E5%8E%9F%E7%90%86_%E4%BB%A5%E5%8F%8A%E5%8C%BA%E5%88%AB.pdf">Redis哨兵_复制_集群的设计原理_以及区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E5%B9%B6%E5%8F%91%E7%AB%9E%E4%BA%89key%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%E8%AF%A6%E8%A7%A3.pdf">Redis并发竞争key的解决方案详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E7%BC%93%E5%AD%98%E5%92%8CMySQL%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.pdf">Redis缓存和MySQL数据一致性的解决方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F_%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF_%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">Redis缓存穿透_缓存击穿_缓存雪崩面试题解析</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/Redis%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">Redis缓存雪崩面试题</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Redis/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">缓存击穿面试题</a><h3 id="ReentrantReadWriteLock"><a href="#ReentrantReadWriteLock" class="headerlink" title="ReentrantReadWriteLock"></a>ReentrantReadWriteLock</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/ReentrantReadWriteLock/ReentrantReadWriteLock%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E4%B8%8E%E9%94%81%E8%8E%B7%E5%8F%96.pdf">ReentrantReadWriteLock的实现原理与锁获取</a><h3 id="RocketMQ"><a href="#RocketMQ" class="headerlink" title="RocketMQ"></a>RocketMQ</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RocketMQ/RocketMQ%E7%9A%84%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1_%E5%85%B3%E9%94%AE%E7%89%B9%E6%80%A7%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF.pdf">RocketMQ的架构设计_关键特性与应用场景</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/RocketMQ/%E5%A6%82%E4%BD%95%E4%BB%8E0%E5%88%B01%E8%AE%BE%E8%AE%A1%E4%B8%80%E4%B8%AA%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E4%B8%AD%E9%97%B4%E4%BB%B6.pdf">如何从0到1设计一个消息队列中间件</a><h3 id="single-login"><a href="#single-login" class="headerlink" title="single_login"></a>single_login</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/single_login/%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95%E9%97%AE%E9%A2%98.pdf">单点登录问题</a><h3 id="Spring"><a href="#Spring" class="headerlink" title="Spring"></a>Spring</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/BeanFactory%E5%92%8CFactoryBean%E7%9A%84%E5%8C%BA%E5%88%AB%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">BeanFactory和FactoryBean的区别面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/Spring%E4%B8%ADbean%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8E%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.pdf">Spring中bean的作用域与生命周期</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/Spring%E4%B8%AD%E4%BD%BF%E7%94%A8%E4%BA%86%E5%93%AA%E4%BA%9B%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.pdf">Spring中使用了哪些设计模式</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/Spring%E4%BA%8B%E5%8A%A1%E7%9A%84%E4%BC%A0%E6%92%AD%E5%B1%9E%E6%80%A7%E9%9D%A2%E8%AF%95%E9%A2%98%E8%AF%A6%E8%A7%A3.pdf">Spring事务的传播属性面试题详解</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/%E8%AE%B2%E4%B8%80%E8%AE%B2Springbean%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.pdf">讲一讲Springbean的生命周期</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/%E8%AE%B2%E4%B8%80%E8%AE%B2Spring%E5%BE%AA%E7%8E%AF%E4%BE%9D%E8%B5%96%E5%8F%8A%E8%A7%A3%E5%86%B3%E6%96%B9%E5%BC%8F.pdf">讲一讲Spring循环依赖及解决方式</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/Spring/%E8%B0%88%E8%B0%88%E5%AF%B9SpringAOP%E7%9A%84%E7%90%86%E8%A7%A3.pdf">谈谈对SpringAOP的理解</a><h3 id="springboot"><a href="#springboot" class="headerlink" title="springboot"></a>springboot</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/springboot/springboot%E5%A6%82%E4%BD%95%E8%AE%BE%E7%BD%AE%E5%90%AF%E5%8A%A8%E6%97%B6%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E6%95%B0%E6%8D%AE.pdf">springboot如何设置启动时的初始化数据</a><h3 id="SpringCloud"><a href="#SpringCloud" class="headerlink" title="SpringCloud"></a>SpringCloud</h3></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/Dubbo%E4%B8%8ESpringCloud%E7%9A%84Ribbon_Hystrix_Feign%E7%9A%84%E4%BC%98%E5%8A%A3%E5%8A%BF%E6%AF%94%E8%BE%83.pdf">Dubbo与SpringCloud的Ribbon_Hystrix_Feign的优劣势比较</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/nacos%E6%9D%83%E9%99%90%E6%8E%A7%E5%88%B6%E6%96%B9%E6%A1%88.pdf">nacos权限控制方案</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/Restful_SOAP_RPC_SOA_%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E5%8C%BA%E5%88%AB.pdf">Restful_SOAP_RPC_SOA_微服务之间的区别</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/SpringCloud%E4%B8%8EDubbo%E7%9A%84%E5%AF%B9%E6%AF%94.pdf">SpringCloud与Dubbo的对比</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/SpringCloud%E7%9A%84%E6%A0%B8%E5%BF%83%E6%88%90%E5%91%98_%E4%BB%A5%E5%8F%8A%E6%9E%B6%E6%9E%84%E5%AE%9E%E7%8E%B0%E8%AF%A6%E7%BB%86%E4%BB%8B%E7%BB%8D.pdf">SpringCloud的核心成员_以及架构实现详细介绍</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E4%B8%8Efeign%E8%B6%85%E6%97%B6%E7%9A%84%E7%BA%A0%E8%91%9B_%E8%AF%A5%E5%92%8B%E4%BC%98%E5%8C%96_.pdf">定时任务与feign超时的纠葛_该咋优化_</a></li><li><a href="http://victorfengming.gitee.io/file/pdf/inter/SpringCloud/%E5%BE%AE%E6%9C%8D%E5%8A%A1Dubbo%E5%92%8CSpringCloud%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1_%E4%BC%98%E5%8A%A3%E5%8A%BF%E6%AF%94%E8%BE%83.pdf">微服务Dubbo和SpringCloud架构设计_优劣势比较</a></li></ul><h1 id="tuling"><a href="#tuling" class="headerlink" title="tuling"></a>tuling</h1><ul><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/2020%E5%B9%B4%E6%9C%80%E6%96%B0%E7%89%88--Java+%E6%9C%80%E5%B8%B8%E8%A7%81%E7%9A%84+200++%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB+%E7%AD%94%E6%A1%88%E6%80%BB%E7%BB%93%E6%B1%87%E6%80%BB.pdf">2020年最新版–Java+最常见的+200++面试题汇总+答案总结汇总</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/BIO,NIO,AIO,Netty%E9%9D%A2%E8%AF%95%E9%A2%9835%E9%81%93.pdf">BIO,NIO,AIO,Netty面试题 35道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Dubbo%E9%9D%A2%E8%AF%95%E9%A2%9847%E9%81%93.pdf">Dubbo面试题 47道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/ElasticSearch%E9%9D%A2%E8%AF%95%E9%A2%9830%E9%81%93.pdf">ElasticSearch面试题 30道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Git%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E9%9D%A2%E8%AF%95%E9%A2%9860%E9%81%93.pdf">Git常用命令面试题 60道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Java%E5%9F%BA%E7%A1%80%E9%9D%A2%E8%AF%95%E9%A2%9891%E9%81%93.pdf">Java基础面试题 91道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Java%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E6%9C%80%E5%85%A8%E9%9D%A2%E8%AF%95%E9%A2%98123%E9%81%93.pdf">Java并发编程最全面试题 123道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Java%E5%BC%82%E5%B8%B8%E9%9D%A2%E8%AF%95%E9%A2%9833%E9%81%93.pdf">Java异常面试题 33道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Java%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%88JVM%EF%BC%89%E9%9D%A2%E8%AF%95%E9%A2%9851%E9%81%93.pdf">Java虚拟机（JVM）面试题 51道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Java%E9%9B%86%E5%90%88%E9%9D%A2%E8%AF%95%E9%A2%9852%E9%81%93.pdf">Java集合面试题 52道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/JVM%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98%E8%A7%A3%E6%9E%90.pdf">JVM常见面试题解析</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Kafka%E7%9F%A5%E8%AF%86%E6%B1%87%E6%80%BB18%E9%81%93.pdf">Kafka知识汇总 18道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Linux%E9%9D%A2%E8%AF%95%E9%A2%9850%E9%81%93.pdf">Linux面试题 50道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Memcache%E9%9D%A2%E8%AF%95%E9%A2%9823%E9%81%93.pdf">Memcache 面试题  23道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/MyBatis%E9%9D%A2%E8%AF%95%E9%A2%9837%E9%81%93.pdf">MyBatis面试题 37道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Mybatis%E9%9D%A2%E8%AF%95%E9%A2%98%EF%BC%88%E5%90%AB%E7%AD%94%E6%A1%88%EF%BC%89.pdf">Mybatis面试题（含答案）</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/MySQL%E9%9D%A2%E8%AF%95%E9%A2%9840%E9%81%93.pdf">MySQL面试题 40道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/MySQL%E9%9D%A2%E8%AF%95%E9%A2%98%EF%BC%88%E5%90%AB%E7%AD%94%E6%A1%88%EF%BC%89.pdf">MySQL面试题（含答案）</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/MySQL%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E9%A2%9810%E9%81%93.pdf">MySQL高频面试题 10道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Netty%E9%9D%A2%E8%AF%95%E9%A2%9820%E9%81%93.pdf">Netty面试题 20道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Nginx%E9%9D%A2%E8%AF%95%E9%A2%9823%E9%81%93.pdf">Nginx面试题 23道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/RabbitMQ%E8%A1%A5%E5%85%856%E9%81%93.pdf">RabbitMQ 补充 6道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/RabbitMQ%E9%9D%A2%E8%AF%95%E9%A2%9822%E9%81%93.pdf">RabbitMQ面试题 22道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Redis%E9%9D%A2%E8%AF%95%E9%A2%9842%E9%81%93.pdf">Redis面试题  42道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Redis%E9%9D%A2%E8%AF%95%E9%A2%9870%E9%81%93.pdf">Redis面试题 70道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Redis%E9%9D%A2%E8%AF%95%E9%A2%98%EF%BC%88%E5%90%AB%E7%AD%94%E6%A1%88%EF%BC%89.pdf">Redis面试题（含答案）</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/SpringBoot%E9%9D%A2%E8%AF%95%E9%A2%9830%E9%81%93.pdf">SpringBoot面试题 30道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/SpringBoot%E9%9D%A2%E8%AF%95%E9%A2%9844%E9%81%93.pdf">SpringBoot面试题 44道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/SpringCloud%E9%9D%A2%E8%AF%95%E9%A2%9849%E9%81%93.pdf">SpringCloud面试题 49道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/SpringMVC%E9%9D%A2%E8%AF%95%E9%A2%9829%E9%81%93.pdf">SpringMVC面试题 29道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Spring%E9%9D%A2%E8%AF%95%E9%A2%9875%E9%81%93.pdf">Spring面试题 75道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Spring%E9%9D%A2%E8%AF%95%E9%A2%98%EF%BC%88%E5%90%AB%E7%AD%94%E6%A1%88%EF%BC%89.pdf">Spring面试题（含答案）</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/TCP%EF%BC%8CUDP%EF%BC%8CSocket%EF%BC%8CHttp%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E9%9D%A2%E8%AF%95%E9%A2%9847%E9%81%93.pdf">TCP，UDP，Socket，Http网络编程面试题 47道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Tomcat%E9%9D%A2%E8%AF%95%E9%A2%9814%E9%81%93.pdf">Tomcat面试题 14道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Zookeeper%E9%9D%A2%E8%AF%95%E9%A2%98.pdf">Zookeeper面试题</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Zookeeper%E9%9D%A2%E8%AF%95%E9%A2%9820%E9%81%93.pdf">Zookeeper面试题 20道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/Zookeeper%E9%9D%A2%E8%AF%95%E9%A2%9828%E9%81%93.pdf">Zookeeper面试题 28道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E9%9D%A2%E8%AF%9559%E9%A2%98%EF%BC%88%E5%90%AB%E7%AD%94%E6%A1%88%EF%BC%89.pdf">多线程面试59题（含答案）</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/%E5%A4%A7%E6%95%B0%E6%8D%AE%E9%9D%A2%E8%AF%95%E9%A2%98100%E9%81%93.pdf">大数据面试题 100道</a></li><li><a href="https://victorfengming.gitee.io/file/pdf/tuling/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E9%9D%A2%E8%AF%95%E9%A2%9814%E9%81%93.pdf">设计模式面试题 14道</a></li></ul><h1 id="Book"><a href="#Book" class="headerlink" title="Book"></a>Book</h1><ul><li><a href="https://victorfengming.gitee.io/file/book/ddd/DDD_%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1_%E7%B2%BE%E7%AE%80%E7%89%88.pdf">DDD_领域驱动设计_精简版</a></li><li><a href="https://victorfengming.gitee.io/file/book/ddd/%E5%AE%9E%E7%8E%B0%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1.pdf">实现领域驱动设计</a></li><li><a href="https://victorfengming.gitee.io/file/book/ddd/%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1%E8%BD%AF%E4%BB%B6%E5%A4%8D%E6%9D%82%E6%80%A7%E4%B9%8B%E9%81%93.pdf">领域驱动设计软件复杂性之道</a></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> index </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Mustache简介</title>
      <link href="front/mustache/"/>
      <url>front/mustache/</url>
      
        <content type="html"><![CDATA[<p>Mustache 是一款经典的前端模板引擎，在前后端分离的技术架构下面，前端模板引擎是一种可以被考虑的技术选型，随着重型框架（AngularJS、ReactJS、Vue）的流行，前端的模板技术已经成为了某种形式上的标配，Mustache 的价值在于其稳定和经典： </p><p>主页：<a href="https://github.com/janl/mustache.js/">https://github.com/janl/mustache.js/</a><br>文档：<a href="https://mustache.github.io/mustache.5.html">https://mustache.github.io/mustache.5.html</a>  </p><p>Mustache 在使用的时候，会在页面上出现 { { person} }  这样的标签，载入的时候回显示出来，然后立即被替换掉，这个对于页面的呈现是不够友好的，这是我在使用的过程中遇到的一个痛点。  </p><p>Mustache 功能非常经典，这里就能全部罗列出来：  </p><h3 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h3><p>{ { person} }   </p><h3 id="带有HTML的变量"><a href="#带有HTML的变量" class="headerlink" title="带有HTML的变量"></a>带有HTML的变量</h3><p>{ { { person} } }   </p><h3 id="循环"><a href="#循环" class="headerlink" title="循环"></a>循环</h3><p>{ { #persons} }<br>……<br>{ { /persons} }   </p><p>数组循环的时候可以用.作为下标<br>{  “musketeers”: [“Athos”, “Aramis”, “Porthos”, “D’Artagnan”] }<br>{ { #musketeers} }<br>{ { .} }<br>{ { /musketeers} }   </p><h3 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h3><p>正常使用：<br>{  “name”: {  “first”: “Michael”, “last”: “Jackson” } , “age”: “RIP” }<br>{ { name.first} }  { { name.last} }<br>{ { age} }   </p><p>循环使用：<br>{  “stooges”: [ {  “name”: “Moe” } , {  “name”: “Larry” } , {  “name”: “Curly” }  ] }<br>{ { #stooges} }<br>{ { name} }<br>{ { /stooges} }   </p><h3 id="if-else"><a href="#if-else" class="headerlink" title="if else"></a>if else</h3><p>{ { #person} }<br>……<br>{ { /person} }<br>{ { ^person} }<br>……<br>{ { /person} }   </p><h3 id="布尔判断"><a href="#布尔判断" class="headerlink" title="布尔判断"></a>布尔判断</h3><p>和前面循环的语法是一样的，取决于变量是否是一个数组<br>{ { #person} }<br>……<br>{ { /person} }   </p><h3 id="数组的布尔判断"><a href="#数组的布尔判断" class="headerlink" title="数组的布尔判断"></a>数组的布尔判断</h3><p>当一个数组没有任何值的时候，可能会希望不做任何的显示，所以需要这个判断<br>{ { #persons.length} }<br>……<br>{ { /persons.length} }   </p><h3 id="Lambdas"><a href="#Lambdas" class="headerlink" title="Lambdas"></a>Lambdas</h3><p>遇到和前面的循环和布尔表达式一样，取决于参数的类型<br>{ { #person} }<br>{ { name} }  is awesome.<br>{ { /person} }   </p><p>{  “name”: “Willy”, “person”: function() {  return function(text, render) {  return “<b>“ + render(text) + “</b>“ }  }  }   </p><p>输出<br><b>Willy is awesome.</b>  </p><h3 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h3><p>这玩意儿有啥用呢？<br>{ { ! ignore me } }   </p><h3 id="Trick"><a href="#Trick" class="headerlink" title="Trick"></a>Trick</h3><p>在做<tr></tr>的循环输出的时候，需要使用类似这样的形式（感觉这就是BUG啊，或者是HTML标准的问题？）：<br>``  </p><tr> <td>{ { name} } </td> <td>{ { age} } </td> </tr>    ### 两个核心方法  Mustache.parse(template);  Mustache.render(template, obj);    因为动态载入到 HTML 上的事件或者元素会丢失，所以我封装了一个对模板的缓存：    ```javascript  $(templateKey).each(function(i){       templateExist = false;      $(templateArray).each(function(index){           if (templateArray[index][0] == templateKey+i)          {               templateExist = true;              template = templateArray[index][1];          }        } )                if (templateExist != true)      {           template = $(this).html();          templateArray.push([templateKey+i, template]);      }         Mustache.parse(template);      $(this).html(Mustache.render(template, item.data)).show();      if (callbackFunction)      {           callbackFunction(item.data);      } ;  } )  ```  顺便简单学习了一下 Handlebars，这款也非常的知名，并且是基于 Mustache 的模板引擎：  Handlebars：http://handlebarsjs.com/    如果你希望像传统模板引擎一样可以有函数和参数处理等等的功能，那么 Mustache 就不是好的选择，但是再复杂了往上走的话，就不如选用 `Vue` 了        ]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> front </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>商密算法SM2、SM3、SM4的用途和原理</title>
      <link href="unclass/sm1234/"/>
      <url>unclass/sm1234/</url>
      
        <content type="html"><![CDATA[<p>原文链接： <a href="https://yq.aliyun.com/articles/705759">https://yq.aliyun.com/articles/705759</a></p><h2 id="商密算法SM2、SM3、SM4的用途和原理"><a href="#商密算法SM2、SM3、SM4的用途和原理" class="headerlink" title="商密算法SM2、SM3、SM4的用途和原理"></a>商密算法SM2、SM3、SM4的用途和原理</h2><p><a href="https://yq.aliyun.com/users/c3czzrau2a4ms">北阙青云</a> </p><ul><li><p><a href="https://yq.aliyun.com/tags/type_blog-tagid_28/">安全</a></p></li><li></li><li><p><a href="https://yq.aliyun.com/tags/type_blog-tagid_37/">算法</a></p></li><li></li><li><p><a href="https://yq.aliyun.com/tags/type_blog-tagid_422/">函数</a></p></li><li></li><li><p><a href="https://yq.aliyun.com/tags/type_blog-tagid_423/">加密</a></p></li><li></li><li><p><a href="https://yq.aliyun.com/tags/type_blog-tagid_41352/">商密算法</a></p></li><li></li><li><p><a href="https://yq.aliyun.com/tags/type_blog-tagid_41353/">SM2算法</a></p></li></ul><p>国产商密算法是我国自主研发、具有自主知识产权的一系列密码算法，具有较高安全性，由国家密码局公开并大力推广。我国公开的国产商用密码算法包括SM1、SM2、SM3、SM4、SM7、SM9及祖冲之算法，其中SM2、SM3、SM4最为常用，用于对应替代RSA、DES、3DES、SHA等国际通用密码算法体系。</p><h1 id="SM1对称密码"><a href="#SM1对称密码" class="headerlink" title="SM1对称密码"></a>SM1对称密码</h1><p>SM1 算法是分组密码算法，分组长度为128位，密钥长度都为 128 比特，算法安全保密强度及相关软硬件实现性能与 AES 相当，算法不公开，仅以IP核的形式存在于芯片中。<br>采用该算法已经研制了系列芯片、智能IC卡、智能密码钥匙、加密卡、加密机等安全产品，广泛应用于电子政务、电子商务及国民经济的各个应用领域（包括国家政务通、警务通等重要领域）。</p><h1 id="SM2椭圆曲线公钥密码算法"><a href="#SM2椭圆曲线公钥密码算法" class="headerlink" title="SM2椭圆曲线公钥密码算法"></a>SM2椭圆曲线公钥密码算法</h1><p>SM2算法就是ECC椭圆曲线密码机制，但在签名、密钥交换方面不同于ECDSA、ECDH等国际标准，而是采取了更为安全的机制。另外，SM2推荐了一条256位的曲线作为标准曲线。<br>SM2标准包括总则，数字签名算法，密钥交换协议，公钥加密算法四个部分，并在每个部分的附录详细说明了实现的相关细节及示例。<br>SM2算法主要考虑素域Fp和F2m上的椭圆曲线，分别介绍了这两类域的表示，运算，以及域上的椭圆曲线的点的表示，运算和多倍点计算算法。然后介绍了编程语言中的数据转换，包括整数和字节串，字节串和比特串，域元素和比特串，域元素和整数，点和字节串之间的数据转换规则。详细说明了有限域上椭圆曲线的参数生成以及验证，椭圆曲线的参数包括有限域的选取、椭圆曲线方程参数、椭圆曲线群基点的选取等，并给出了选取的标准以便于验证。最后给椭圆曲线上密钥对的生成以及公钥的验证，用户的密钥对为（s，sP），其中s为用户的私钥，sP为用户的公钥，由于离散对数问题从sP难以得到s，并针对素域和二元扩域给出了密钥对生成细节和验证方式。总则中的知识也适用于SM9算法。<br>在总则的基础上给出了数字签名算法（包括数字签名生成算法和验证算法），密钥交换协议以及公钥加密算法（包括加密算法和解密算法），并在每个部分给出了算法描述，算法流程和相关示例。<br>数字签名算法、密钥交换协议以及公钥加密算法都使用了国家密管理局批准的SM3密码杂凑算法和随机数发生器。数字签名算法、密钥交换协议以及公钥加密算法根据总则来选取有限域和椭圆曲线，并生成密钥对。</p><p>SM2算法在很多方面都优于RSA算法。</p><h1 id="SM3杂凑算法"><a href="#SM3杂凑算法" class="headerlink" title="SM3杂凑算法"></a>SM3杂凑算法</h1><p>SM3密码杂凑（哈希、散列）算法给出了杂凑函数算法的计算方法和计算步骤，并给出了运算示例。此算法适用于商用密码应用中的数字签名和验证，消息认证码的生成与验证以及随机数的生成，可满足多种密码应用的安全需求。在SM2，SM9标准中使用。<br>此算法对输入长度小于2的64次方的比特消息，经过填充和迭代压缩，生成长度为256比特的杂凑值，其中使用了异或，模，模加，移位，与，或，非运算，由填充，迭代过程，消息扩展和压缩函数所构成。具体算法及运算示例见SM3标准。</p><h1 id="SM4对称算法"><a href="#SM4对称算法" class="headerlink" title="SM4对称算法"></a>SM4对称算法</h1><p>此算法是一个分组算法，用于无线局域网产品。该算法的分组长度为128比特，密钥长度为128比特。加密算法与密钥扩展算法都采用32轮非线性迭代结构。解密算法与加密算法的结构相同，只是轮密钥的使用顺序相反，解密轮密钥是加密轮密钥的逆序。<br>此算法采用非线性迭代结构，每次迭代由一个轮函数给出，其中轮函数由一个非线性变换和线性变换复合而成，非线性变换由S盒所给出。其中rki为轮密钥，合成置换T组成轮函数。轮密钥的产生与上图流程类似，由加密密钥作为输入生成，轮函数中的线性变换不同，还有些参数的区别。SM4算法的具体描述和示例见SM4标准。</p><h1 id="SM7对称密码"><a href="#SM7对称密码" class="headerlink" title="SM7对称密码"></a>SM7对称密码</h1><p>SM7算法，是一种分组密码算法，分组长度为128比特，密钥长度为128比特。SM7适用于非接触式IC卡，应用包括身份识别类应用(门禁卡、工作证、参赛证)，票务类应用(大型赛事门票、展会门票)，支付与通卡类应用（积分消费卡、校园一卡通、企业一卡通等）。</p><h1 id="SM9标识密码算法"><a href="#SM9标识密码算法" class="headerlink" title="SM9标识密码算法"></a>SM9标识密码算法</h1><p>为了降低公开密钥系统中密钥和证书管理的复杂性，以色列科学家、RSA算法发明人之一Adi Shamir在1984年提出了标识密码（Identity-Based Cryptography）的理念。标识密码将用户的标识（如邮件地址、手机号码、QQ号码等）作为公钥，省略了交换数字证书和公钥过程，使得安全系统变得易于部署和管理，非常适合端对端离线安全通讯、云端数据加密、基于属性加密、基于策略加密的各种场合。2008年标识密码算法正式获得国家密码管理局颁发的商密算法型号：SM9(商密九号算法)，为我国标识密码技术的应用奠定了坚实的基础。<br>SM9算法不需要申请数字证书，适用于互联网应用的各种新兴应用的安全保障。如基于云技术的密码服务、电子邮件安全、智能终端保护、物联网安全、云存储安全等等。这些安全应用可采用手机号码或邮件地址作为公钥，实现数据加密、身份认证、通话加密、通道加密等安全应用，并具有使用方便，易于部署的特点，从而开启了普及密码算法的大门。</p><h1 id="ZUC祖冲之算法"><a href="#ZUC祖冲之算法" class="headerlink" title="ZUC祖冲之算法"></a>ZUC祖冲之算法</h1><p>祖冲之序列密码算法是中国自主研究的流密码算法,是运用于移动通信4G网络中的国际标准密码算法,该算法包括祖冲之算法(ZUC)、加密算法(128-EEA3)和完整性算法(128-EIA3)三个部分。目前已有对ZUC算法的优化实现，有专门针对128-EEA3和128-EIA3的硬件实现与优化。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> summer </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>spring笔记01</title>
      <link href="java/spring/spring-note1/"/>
      <url>java/spring/spring-note1/</url>
      
        <content type="html"><![CDATA[<h3 id="Spring-简介"><a href="#Spring-简介" class="headerlink" title="Spring 简介"></a>Spring 简介</h3><p>Spring框架由Rod Johnson开发,2004年发布了 Spring框架的第一版.Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅仅是与特定应用相关的部分,从而大大提高了企业应用的开发效率.</p><p>Spring总结起来优点如下:</p><ul><li>低侵入式设计,代码的污染极低.</li><li>独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺.</li><li>Spring的IoC容器降低了业务对象替换的复杂性,提高了组件之间的解耦.</li><li>Spring的AOP支持允许将一些通用任务如安全,事务,日志等进行集中式管理,从而提供了更好的复用.</li><li>Spring的高度开发性,并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部.</li></ul><p>Spring框架的组成结构图如下所示:</p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/java/spring/spring01.png" alt="Spring组成结构图"></p><h3 id="Spring-的核心机制"><a href="#Spring-的核心机制" class="headerlink" title="Spring 的核心机制"></a>Spring 的核心机制</h3><h4 id="管理Bean"><a href="#管理Bean" class="headerlink" title="管理Bean"></a>管理Bean</h4><p>程序主要是通过Spring容器来访问容器中的Bean,ApplicationContext是Spring容器最常用的接口,该接口如下两个实现类:</p><ul><li>ClassPathXMLApplicationContext:从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器.</li><li>FileSystemXMLApplicationContext:从文件系统的相对路径或绝对路径下去搜索配置文件,并根据配置文件来创建Spring容器.</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BeanTest</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String args[])</span> <span class="keyword">throws</span> Exception</span>&#123;</span><br><span class="line">        ApplicationContext ctx = <span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="string">&quot;beans.xml&quot;</span>);</span><br><span class="line">        Person p = ctx.getBean(<span class="string">&quot;person&quot;</span>, Person.class);</span><br><span class="line">        p.say();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Eclipse-使用-Spring"><a href="#Eclipse-使用-Spring" class="headerlink" title="Eclipse 使用 Spring"></a>Eclipse 使用 Spring</h3><p>在eclipse等IDE工具中,用户可以自建User Library,然后把Spring的Jar包都放入其中,当然也可以将Jar包直接放在项目的/WEB-INF/lib目录下,但是如果使用User Library,在项目发布时,需要将用户库所引用的Jar文件随应用一起发布,就是将User Library所使用的Jar复制到/WEB-INF/lib 目录下,这是因为对于一个Web应用,Eclipse部署Web应用时不会将用户库的Jar文件复制到/WEB-INF/lib下,需要手动复制.</p><h3 id="依赖注入"><a href="#依赖注入" class="headerlink" title="依赖注入"></a>依赖注入</h3><p>Spring框架的核心功能有两个:</p><ul><li>Spring容器作为超级大工厂,负责创建,管理所有的Java对象,这些Java对象被称为Bean.</li><li>Spring容器管理容器中Bean之间的依赖关系,Spring使用一种被称为”依赖注入的方式来管理Bean之间的依赖关系.</li></ul><p>使用依赖注入,不仅可以为Bean注入普通的属性值,还可以注入其他Bean的引用.依赖注入是一种优秀的解耦方式,其可以让Bean以配置文件组织在一起,而不是以硬编码的方式耦合在一起.</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> Spring </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>cucumber介绍</title>
      <link href="unclass/cucumber-note01/"/>
      <url>unclass/cucumber-note01/</url>
      
        <content type="html"><![CDATA[<h3 id="cucumber介绍"><a href="#cucumber介绍" class="headerlink" title="cucumber介绍"></a>cucumber介绍</h3><p>cucumber 是一个支持BDD(behavior Driven Development),即行为驱动开发的自动化测试框架.在进行单元测试或者集成测试之前,事先将测试的步骤和验证信息用通用的语言(英语)定义好,使得测试的步骤、单元测试和集成测试每一步执行的目的能被非开发人员读懂,并且写单元测设和集成测试的人员可以根据事先写好的框架进行代码的编写,达到行为驱动开发的目的.</p><h3 id="cucumber框架的搭建"><a href="#cucumber框架的搭建" class="headerlink" title="cucumber框架的搭建"></a>cucumber框架的搭建</h3><ol><li>将cucumber插件导入eclipse中,此处同其他插件导入方法相同,不作说明.</li><li>新建Java工程,将cucumber所需要的jar包导入Java工程中(最好新建一个文件夹,将jar包放到该文件夹下).</li><li>通过Build Path添加刚导入的JARs</li><li>新建用来定义步骤的feature格式的文件,新建的feature格式文件会自动填写模板文件,具体使用方法后续说明.同上,最好将其放在特定的文件夹 里,本例Feature文件夹.</li><li>将被测试的包导入Java工程中,本例测试一个简单的Calculator类.</li><li>新建一个包,包名必须为test.java或main.java 否则后续创建cucumber定义步骤时会出错.</li><li>在test.java包中新建一个Step-Definition class.</li></ol><h3 id="cucumber框架相关文件及其内容的说明"><a href="#cucumber框架相关文件及其内容的说明" class="headerlink" title="cucumber框架相关文件及其内容的说明"></a>cucumber框架相关文件及其内容的说明</h3><ol><li>.feature文件<br>定义了测试的步骤,包括以下几个关键字<br>Feature: 一个.feature文件有且仅有一个Feature关键字.描述要测试的对象,一般为测试标题.</li></ol><p>Scenario: 一个.feature文件可以有0个或多个Scenario关键字.测试对象的场景,如测试Add()方法,可以有两个整数相加的和两个负数相加等多种场景.</p><p>Given: 一个.feature文件有且仅有一个Given关键字.相当于测试用例中的预置条件.如想要表达多个预置条件,可以通过And关键字添加.</p><p>When: 一个.feature文件有且仅有一个When关键字.具体的操作步骤,类似于测试用例的中的预期结果.如想要表达多个预期结果,可以通过And关键字添加.</p><p>Then: 一个.feature文件有且仅有一个Then关键字.相当于测试用例的中的预期结果.如想要表达多个预期结果,可以通过and关键字添加.</p><p>And: 一个.feature文件可以有0个或多个And关键字.And元素可以补充额外的预置条件或操作步骤.</p><p>But: 一个.feature文件可以有0个或多个But关键字.But和And一样,可以同Given、When、Then连用,用于添加否定类型的描述,一般只适用于负面条件.比如:</p><p>THEN login should be successful.</p><p>BUT home page should not be missing</p><p>Scenario Outline: 一个.feature文件可以有0个或多个Scenario Outline 关键字.用于场景中有多数组数值时,必须配合Example一起使用,成对出现.<br>Example: 和Scenario Outline成对出现,其下有多组测试数值的列表 </p><ol start="2"><li>Step-definition文件<br>cucumber的Step-definition和其他的Java格式文件基本相同,但是在创建时可以根据需要选择性勾选并自动添加Give,When,Then,And,But注释.</li></ol><p>完成后会自动生成一个Java模板文件,包括了之前勾选的注释,本例勾选了Given,When,Then和And.注释的格式为:</p><p>@关键字(“^*********$”)<br>@Given(“^you are in Given annotation$”)</p><p>关键字后括号里的内容必须和先前定义的.feature文件的关键字的内容一一对应,识别大小写并且包括空格数目等都要一样,以^开头,$结尾.<br>注释之后为具体实现的方法,在方法中添加符合关键字后描述的操作代码.</p><ol start="3"><li>测试执行文件<br>cucumber 的测试执行文件一般为一个空的Junit Test Case, 即不需要Test注释,更不需要Before和After等注释.当必须添加RunWith注释和CucumberOption注释.<br>RunWith注释每一个Cucumber框架的测试文件都是相同的,为RunWith(Cucumber.class). CucumberOption注释的内容是根据实际情况需要手动更改的.</li></ol><p>CucumberOption注释选项一般有features,glue,monochrome和dryrun等.其中.feature和glue是必写项,monochrome和dryrun选填项.<br>feature定义了.feature文件的相对路径,格式为features=”.feature文件在改工程的文件夹/.feature文件的名字”.</p><p>eg.features=”Feature/calculatorAdd.feature”</p><p>glue定义了Step-difinition的包名,格式为glue=”完整的包名”.<br>eg.test.javacucumberDefinition.</p><p>monochrome选项有两个值,分别为true和false,默认为false,格式为monochrome=boolean.用来控制测试结果的可读性,当monochrome=true时,测试结果可读性更好.monochrome=true时,测试结果可读性比较差.</p><p>dryrun选项暂时不了解</p><p>cucumber框架的使用</p><p>通过以上介绍,cucumber框架基本搭建完成,对cucumber各文件的作用也有所了解,接下来就是通过对框架的修改来实现一个简单的BDD模式的单元测试.<br>测试Calculator类中的Add()成员方法</p><ol><li><p>新建testAdd.feature文件,并修改其内容</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">@tag</span><br><span class="line">Feature: Test add <span class="function"><span class="keyword">function</span> <span class="title">of</span> <span class="title">calculator</span></span></span><br><span class="line"><span class="function">@<span class="title">tag1</span></span></span><br><span class="line"><span class="function"><span class="title">Scenario</span>: <span class="title">Add</span> <span class="title">two</span> <span class="title">numbers</span></span></span><br><span class="line"><span class="function"><span class="title">Given</span> <span class="title">init</span> <span class="title">the</span> <span class="title">object</span> <span class="title">of</span> <span class="title">calculator</span></span></span><br><span class="line"><span class="function"><span class="title">When</span> <span class="title">clear</span> <span class="title">the</span> <span class="title">result</span> <span class="title">to</span> <span class="title">zero</span></span></span><br><span class="line"><span class="function"><span class="title">And</span> <span class="title">and</span> <span class="title">num1</span> <span class="title">and</span> <span class="title">num2</span></span></span><br><span class="line"><span class="function"><span class="title">Then</span> <span class="title">check</span> <span class="title">the</span> <span class="title">actual</span> <span class="title">result</span></span></span><br></pre></td></tr></table></figure></li><li><p>新建stepDefinition.java文件,使用Given,when,Then,和And关键字,修改注释内容并根据注释内容填写方法中的代码.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">package test.java.cucumberDefinition</span><br><span class="line"></span><br><span class="line">import cucumber.api.java.en.Given;</span><br><span class="line">import cucumber.api.java.en.When;</span><br><span class="line">import cucumber.api.java.en.Then;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">import static org.junit.Assert.assertEquals;</span><br><span class="line"></span><br><span class="line">import com.calculator.Calculator;</span><br><span class="line"></span><br><span class="line">import cucumber.api.java.en.And;</span><br><span class="line"></span><br><span class="line">public class stepDefinition&#123;</span><br><span class="line">    Calculator cal;</span><br><span class="line">    int result;</span><br><span class="line">    @Given(&quot;init the object of calculator$&quot;)</span><br><span class="line">    public void given() throws Throwable&#123;</span><br><span class="line">        cal &#x3D; new Calculator();</span><br><span class="line">    &#125;   </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@When(&quot;^clear the result to zero$&quot;)</span><br><span class="line">public void when() throws Throwable&#123;</span><br><span class="line">    cal.clear();      </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@Then(&quot;^add num1 and num2$&quot;)</span><br><span class="line">public void then() throws Throwable&#123;</span><br><span class="line">    cal.add(2);</span><br><span class="line">    cal.add(3);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@And(&quot;^check the actual result$&quot;)</span><br><span class="line">public void and() throws Throwable &#123;</span><br><span class="line">int expected &#x3D; 5;</span><br><span class="line">result &#x3D; cal.getResult();</span><br><span class="line">assertEquals(expected,result);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p>新建一个Junit Test Case，并将其内容清空，最后添加RunWith和CucumberOptions注释。</p></li></ol><p>package com.calculator.test;</p><p>import static org.junit.Assert.*;</p><p>import org.junit.Test;<br>import org.junit.runner.RunWith;</p><p>import cucumber.api.CucumberOptions;<br>import cucumber.api.junit.Cucumber;</p><p>@RunWith(Cucumber.class)<br>@CucumberOptions(features=”Feature/calculatorAdd.feature”</p><p>,glue=”test.java.cucumberDefinition”,monochrome=true)<br>public class testAdd {</p><p>}<br>4. 右键testAdd.java，执行run as junit case进行测试。</p><h2 id="cucumber简单介绍"><a href="#cucumber简单介绍" class="headerlink" title="cucumber简单介绍"></a>cucumber简单介绍</h2><h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p>cucumber是一个能够理解用普通语言描述的测试用例的行为驱动开发(BDD)的自动化测试工具,<br>其本质上是使用根据正则表达式匹配自然语言,然后依次执行对应的方法,以达到测试的目的.</p><p>优点:</p><ul><li>支持不同的语言,例如Java, .net, Ruby</li><li>它充当业务与技术间的桥梁的角色.可以通过在纯英文文本中创建一个测试用例来实现这一点</li><li>他允许在不知道任何代码的情况下编写测试脚本,它允许非程序员参与.</li><li>由于简单的测设脚本架构,cucumber提供了代码可重用性</li></ul><h3 id="组成"><a href="#组成" class="headerlink" title="组成"></a>组成</h3><p>组成:Feature,Step_definitions,Cucumber command</p><p>Feature:功能</p><ul><li>基于Gerkins.支持多种语言,</li><li>以.feature命名</li><li>每个features包含多个scenarios,每个scenarios包含多个step</li></ul><p>Step_definitions</p><ul><li>根据feature文件中定义的step编写对应的测试代码.</li></ul><p>cucumber command</p><ul><li>运行: *.feature 文件.cucumber会分析feature文件中定义的step,然后去step-definition找到相匹配的step,执行step中的代码.</li><li>对于cucumber而言,除了顶层的features文件夹是强制性的之外,其它目录结构都不是强制性的,cucumber将对features文件夹下的所有内容进行扁平化(flatten)处理和首字母排序.具体来说,cucumber在运行时,首先将递归的执行features文件夹下的所有Ruby文件(其中则包括Step文件),然后通过相同的方式执行Feature文件.但是,如果features文件夹下存在support子文件夹,并且support下有名为env.rb的文件,cucumber将首先执行该文件,然后执行support下的其他文件,在递归执行features下的其他文件</li></ul><p> 在cucumber项目中,当我们执行cucumber命令时,会首先执行features/support目录下的几个支持文件:env,hooks,world和transforms.cucumber的这些系统文件的执行顺序如下图所示:</p><ol><li>env.rb:通常用于准备环境变量;</li><li>transform.rb: 用于转换feature描述中需要正则匹配的字符串,通过调用cucumber::RbRupport::RbDsl的Transform方法,完成字符串到自定义类型的转换;</li><li>hooks.rb: 是一个钩子,其中定义了Before,After 与 at_exit方法,通过提供block执行场景前,后以及退出执行后的相关逻辑</li><li>world.rb: World可以看做是cucumber在每个场景之前所要创建的对象的实例,它使得每个Step Definition可以调用该实例的方法.World在cucumber中被定义为方法,接受可变参数mudules,以及一个proc</li></ol><p> Gerkin(cucumber的语言输出)<br> Gherkin是自然语言测试的简单语法.一个完整的测试是由多个step组成的,step即最小单元,如何复用step是非常关键的问题.多个step组成一个SCenario,即一个完整的测试case.多个Scenario组成一个Feature,即一组相关的测试case.</p><p> 关键字</p><ul><li>Feature</li><li>Example(or Scenario)</li><li>Given, When, Then, And, But</li></ul>]]></content>
      
      
      
    </entry>
    
    
    
    <entry>
      <title>cucumber自动化测试</title>
      <link href="unclass/cucumber-note02/"/>
      <url>unclass/cucumber-note02/</url>
      
        <content type="html"><![CDATA[<h3 id="cucumber自动化测试"><a href="#cucumber自动化测试" class="headerlink" title="cucumber自动化测试"></a>cucumber自动化测试</h3><p>cucumber是一款测试工具.可用于大多数主流编程语言.比如Java,JS,Ruby,C++,lua,Android,kotlin,C#/F#,PHP,Python,Go,groovy,scala等等.</p><p>其中,Java,JS,Ruby的代码托管在cucumber下.官方建议选择与生产代码相同的平台或编程语言的实现.</p><p>本文主要是Java平台下的介绍教程.使用方法非常简单,创建一个mvn工程,在pom.xml文件引入一下依赖即可.</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.cucumber<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>cucumber-java8<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.2.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>也可根据骨架创建cucumber项目.</p><h3 id="创建一个空的cucumber项目"><a href="#创建一个空的cucumber项目" class="headerlink" title="创建一个空的cucumber项目"></a>创建一个空的cucumber项目</h3><p>我们首先使用cucumber-prototype Maven插件创建一个新项目目录.打开终端,转到要创建项目的目录(比如本文是hellocucumber),运行一下命令:</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">mvn archetype:generate                      \</span><br><span class="line">   -DarchetypeGroupId=io.cucumber           \</span><br><span class="line">   -DarchetypeArtifactId=cucumber-archetype \</span><br><span class="line">   -DarchetypeVersion=<span class="number">2</span>.<span class="number">3</span>.<span class="number">1</span>.<span class="number">2</span>               \</span><br><span class="line">   -DgroupId=hellocucumber                  \</span><br><span class="line">   -DartifactId=hellocucumber               \</span><br><span class="line">   -Dpackage=hellocucumber                  \</span><br><span class="line">   -Dversion=<span class="number">1</span>.<span class="number">0</span>.<span class="number">0</span>-SNAPSHOT                 \</span><br><span class="line">   -DinteractiveMode=false</span><br></pre></td></tr></table></figure><p>你应该得到如下结果:</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[INFO] Project created from Archetype <span class="keyword">in</span> <span class="built_in">dir</span>: hellocucumber/cucumber</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>切换到刚才运行命令创建的目录:</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> hellocucumber</span><br></pre></td></tr></table></figure><p>在idea中打开项目:<br>文件-&gt;打开…-&gt;(选择pom.xml)<br>选择open as project</p><p>现在,您已经安装了一个简单的cucumber项目.</p><h3 id="验证cucumber安装"><a href="#验证cucumber安装" class="headerlink" title="验证cucumber安装"></a>验证cucumber安装</h3><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn test</span><br></pre></td></tr></table></figure><p>您应该看到如下内容:</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">-------------------------------------------------------</span><br><span class="line"> T E S T S</span><br><span class="line">-------------------------------------------------------</span><br><span class="line">Running hellocucumber.RunCucumberTest</span><br><span class="line">No features found at [classpath:hellocucumber]</span><br><span class="line"></span><br><span class="line">0 Scenarios</span><br><span class="line">0 Steps</span><br><span class="line">0m0.004s</span><br><span class="line"></span><br><span class="line">Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.541 sec</span><br><span class="line"></span><br><span class="line">Results :</span><br><span class="line"></span><br><span class="line">Tests run: 0, Failures: 0, Errors: 0, Skipped: 0</span><br><span class="line"></span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">cucumber的输出告诉我们它没有找到任何可以运行的东西.</span><br><span class="line"></span><br><span class="line">### 写一个scenario(场景)</span><br><span class="line">当我们使用cucumber进行行为驱动开发时,我们使用具体的例子来指定我们希望软件做什么.scenario是在生产代码之前编写的.它们以可执行规范的形式开始生命.随着生产代码的出现,场景扮演了事实文档和自动化测试的角色.</span><br><span class="line"></span><br><span class="line">在cucumber中,一个example称为scenario. scenario定义在.feature文件中,这些文件存储在src/test/resources/hellocucumber目录(或子目录)中.</span><br><span class="line"></span><br><span class="line">一个具体的例子就是:星期天不是星期五.</span><br><span class="line"></span><br><span class="line">创建一个名为`src/test/resources/hellocucumber/is_it_friday_yet.feature`的文件,文件包括以下内容:</span><br><span class="line"></span><br><span class="line">```xml</span><br><span class="line">Feature: Is it Friday yet?</span><br><span class="line">  Everybody wants to know when it&#x27;s Friday</span><br><span class="line"></span><br><span class="line">  Scenario: Sunday isn&#x27;t Friday</span><br><span class="line">    Given today is Sunday</span><br><span class="line">    When I ask whether it&#x27;s Friday yet</span><br><span class="line">    Then I should be told &quot;Nope&quot;</span><br></pre></td></tr></table></figure><p>这个文件的第一行以关键字’’’Feature’’’开始: 后面跟着一个名称.最好使用与文件名类似的名称.</p><p>第二行是对该特性的简要描述.cucumber并不执行这一行,它只是一个文档.</p><p>第4行,场景:sunday is not friday 是一个scenario, 它是说明软件应该如何工作的具体示例.<br>最后三行以Given开头,when和then是我们的场景的步骤.这就是cucumber将要执行的操作.</p><h3 id="看一个未定义的scenario报告"><a href="#看一个未定义的scenario报告" class="headerlink" title="看一个未定义的scenario报告"></a>看一个未定义的scenario报告</h3><p>现在我们有了场景,我们可以让cucumber执行它:<br>mvn test<br>cucumber告诉我们有一个undefined的场景和三个undefined的步骤.它还建议我们使用一些代码片段来define这些步骤:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">-------------------------------------------------------</span><br><span class="line"> T E S T S</span><br><span class="line">-------------------------------------------------------</span><br><span class="line">&#96;&#96;&#96;java</span><br><span class="line">Running hellocucumber.RunCucumberTest</span><br><span class="line">Feature: Is it Friday yet?</span><br><span class="line">  Everybody wants to know when it&#39;s Friday</span><br><span class="line"></span><br><span class="line">  Scenario: Sunday isn&#39;t Friday        # hellocucumber&#x2F;is_it_friday_yet.feature:4</span><br><span class="line">    Given today is Sunday              # null</span><br><span class="line">    When I ask whether it&#39;s Friday yet # null</span><br><span class="line">    Then I should be told &quot;Nope&quot;       # null</span><br><span class="line"></span><br><span class="line">1 Scenarios (1 undefined)</span><br><span class="line">3 Steps (3 undefined)</span><br><span class="line">0m0.040s</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">You can implement missing steps with the snippets below:</span><br><span class="line"></span><br><span class="line">@Given(&quot;^today is Sunday$&quot;)</span><br><span class="line">public void today_is_Sunday() &#123;</span><br><span class="line">    &#x2F;&#x2F; Write code here that turns the phrase above into concrete actions</span><br><span class="line">    throw new PendingException();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@When(&quot;^I ask whether it&#39;s Friday yet$&quot;)</span><br><span class="line">public void i_ask_whether_it_s_Friday_yet() &#123;</span><br><span class="line">    &#x2F;&#x2F; Write code here that turns the phrase above into concrete actions</span><br><span class="line">    throw new PendingException();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@Then(&quot;^I should be told \&quot;([^\&quot;]*)\&quot;$&quot;)</span><br><span class="line">public void i_should_be_told(String arg1) &#123;</span><br><span class="line">    &#x2F;&#x2F; Write code here that turns the phrase above into concrete actions</span><br><span class="line">    throw new PendingException();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="重构"><a href="#重构" class="headerlink" title="重构"></a>重构</h2><p>现在我们有了工作代码，我们应该做一些重构:</p><p>我们应该将isItFriday方法从测试代码移到生产代码中。<br>我们可以在某个时候从步骤定义中提取helper方法，用于我们在几个地方使用的方法。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>在这个简短的教程中，您已经了解了如何安装Cucumber，如何遵循BDD流程来开发一个非常简单的方法，以及如何使用该方法来评估多个场景!</p><p>作者：Graddy<br>链接：<a href="https://www.jianshu.com/p/60122d38a08a">https://www.jianshu.com/p/60122d38a08a</a><br>来源：简书<br>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。</p><hr><h1 id="自动化测试之cucumber-一"><a href="#自动化测试之cucumber-一" class="headerlink" title="自动化测试之cucumber(一)"></a>自动化测试之cucumber(一)</h1><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>cucumber是BDD(behavior-driven development,行为驱动开发)的一个自动化测试的副产品.它使用自然语言来描述测试,使得非程序员可以理解他们.</p><p>Gherkin是这种自然语言测试的简单语法,而cucumber是可以执行它们的工具.关于BDD有兴趣自行了解.附cucumber<a href="https://links.jianshu.com/go?to=https://cucumber.io/">官网链接</a>,里面也有关于BDD的信息.</p><p>cucumber本质上是使用根据正则表达式匹配自然语言,然后依次执行对应的方法,以达到测试的目的.</p><p>本文基本上只是官网的搬运工,摘要了部分信息,最好还是看官网文档.</p><h2 id="Gherkin"><a href="#Gherkin" class="headerlink" title="Gherkin"></a>Gherkin</h2><p>gherkin是自然语言测试的简单语法.<br>一个完整的测试是由多个step组成的,step即最小单元,如何复用step是非常关键的问题.多个step组成一个scenario,即一个完整的测试case.多个scenario组成一个Feature,即一组相关的测试case.</p><h2 id="关键字"><a href="#关键字" class="headerlink" title="关键字"></a>关键字</h2><ul><li>Feature</li><li>Example(or Scenario)</li><li>Given, When, Then, And, But(steps)</li><li>Background</li><li>Scenario Outline(or Scenario Template)</li><li>Examples(or Scenarios)</li></ul><h2 id="一个简单的例子"><a href="#一个简单的例子" class="headerlink" title="一个简单的例子"></a>一个简单的例子</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Feature: Is it friday yet?</span><br><span class="line">  <span class="built_in">this</span> is a descriptions</span><br><span class="line">  Everybody want to know when it<span class="string">&#x27;s Friday</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">  Scenario: Sunday isn&#x27;</span>t Friday</span><br><span class="line">    Given today is Sunday</span><br><span class="line">    When I ask whether it<span class="string">&#x27;s Friday yet</span></span><br><span class="line"><span class="string">    Then I should be told &quot;Nope&quot;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">  Scenario: Friday is Friday</span></span><br><span class="line"><span class="string">    Given today is Friday</span></span><br><span class="line"><span class="string">    When I ask whether it&#x27;</span>s Friday yet</span><br><span class="line">    Then I should be told <span class="string">&quot;TGIF&quot;</span></span><br></pre></td></tr></table></figure><h2 id="Feature"><a href="#Feature" class="headerlink" title="Feature"></a>Feature</h2><p>Feature是所有测试的开头.后面跟一段描述性的文字,表明这个测试文件是干什么的.</p><h2 id="description"><a href="#description" class="headerlink" title="description"></a>description</h2><p>description是一段扩展性的文字描述,可以跟在Feature,Example,Background,Scenario,Scenario Outline 下面.</p><h2 id="Example和Scenario"><a href="#Example和Scenario" class="headerlink" title="Example和Scenario"></a>Example和Scenario</h2><p>Example和Scenario是一对儿同义词,是一个具体的测试case,包含了多个step.一般情况下,都是由Given(给定一个初始条件),When(发生了什么),Then(结果是什么)组成的.</p><h2 id="Steps"><a href="#Steps" class="headerlink" title="Steps"></a>Steps</h2><p>step是cucumber的最下单元,每个step是由Given,When,Then,And,或者But开头的.如果关键词后面的内容是完全一样的话,那么cucumber会认为这两句话是重复的,哪怕前面的关键词不一样,如</p><hr><h1 id="Gherkin是什么"><a href="#Gherkin是什么" class="headerlink" title="Gherkin是什么"></a>Gherkin是什么</h1><p>Gherkin,cucumber解释器可以理解的语言.这是一个商业可读性,领域特定语言,描述软件的行为而不需要关心这个行为的如何实现的.</p><p>Gherkin有两个目的 - 文档和自动化测试.第三个额外特色:当它被标记为红色叉叉时,让你知道接下来的代码如何写.</p><p>Gherkin的语法定义为Treetop语法(Treetop–基于Ruby的PEG解析器生成器)所以可以被cucumber解释执行(cucumber是一个解释程序,就像ruby命令执行解释.rb文件里的Ruby代码一样,cucumber用来执行解释.Feature文件里的Gehrkin代码.)该语法适用在不同语言中,让您的团队可以使用自己的语言中的关键字.</p><p>个人理解:<br>Gherkin是一种语法,使用Given,when,then等关键来描述一个User Story.形成的代码不论是User,BA都能读懂的形式,同时也非常便于使用specflow转化成BDD所需要的文件.</p><h3 id="通用约定"><a href="#通用约定" class="headerlink" title="通用约定"></a>通用约定</h3><p>-&gt; Gherkin的单个文件包含对一个功能点的描述<br>-&gt; 源文件使用.feature作为扩展名</p><h3 id="Gherkin语法"><a href="#Gherkin语法" class="headerlink" title="Gherkin语法"></a>Gherkin语法</h3><p>像Python和YAML,Gherkin是一种面向行的语言.使用缩进来定义结构.行结尾终止语句(例如,步骤).空格或制表符可用于缩进(但空格更方便些),每一行以关键字开始.</p><p>注释允许出现在文件的任何一行,但是要以#开始,仅支持单行注释.</p><p>当你开始运行一个行为时,feature关键字的后面部分,也就是详细步骤,这是一段Ruby风格的代码片段,会被解析器分析出所有的功能,情景和步骤.</p><p>Gherkin文件格式如下:<br>成人带婴儿旅客,联程,一件行李,两段均进行ET改期.feature</p>]]></content>
      
      
      
    </entry>
    
    
    
    <entry>
      <title>ansible简介</title>
      <link href="operation/ansible-introduce/"/>
      <url>operation/ansible-introduce/</url>
      
        <content type="html"><![CDATA[<p>#ansible<br>Ansible是一款简单的运维自动化工具，只需要使用ssh协议连接就可以来进行系统管理，自动化执行命令，部署等任务。</p><h3 id="Ansible的特点"><a href="#Ansible的特点" class="headerlink" title="Ansible的特点"></a>Ansible的特点</h3><h5 id="1、ansible不需要单独安装客户端，也不需要启动任何服务"><a href="#1、ansible不需要单独安装客户端，也不需要启动任何服务" class="headerlink" title="1、ansible不需要单独安装客户端，也不需要启动任何服务"></a>1、ansible不需要单独安装客户端，也不需要启动任何服务</h5><h5 id="2、ansible是python中的一套完整的自动化执行任务模块"><a href="#2、ansible是python中的一套完整的自动化执行任务模块" class="headerlink" title="2、ansible是python中的一套完整的自动化执行任务模块"></a>2、ansible是python中的一套完整的自动化执行任务模块</h5><h5 id="3、ansible-playbook-采用yaml配置，对于自动化任务执行过一目了然"><a href="#3、ansible-playbook-采用yaml配置，对于自动化任务执行过一目了然" class="headerlink" title="3、ansible playbook 采用yaml配置，对于自动化任务执行过一目了然"></a>3、ansible playbook 采用yaml配置，对于自动化任务执行过一目了然</h5><h3 id="Ansible组成结构"><a href="#Ansible组成结构" class="headerlink" title="Ansible组成结构"></a>Ansible组成结构</h3><h5 id="Ansible"><a href="#Ansible" class="headerlink" title="Ansible"></a>Ansible</h5><p>是Ansible的命令工具，核心执行工具；一次性或临时执行的操作都是通过该命令执行。</p><h5 id="Playbook"><a href="#Playbook" class="headerlink" title="Playbook"></a>Playbook</h5><p>任务剧本（又称任务集），编排定义Ansible任务集的配置文件，由Ansible顺序依次执行，yaml格式。</p><h5 id="Inventory"><a href="#Inventory" class="headerlink" title="Inventory"></a>Inventory</h5><p>Ansible管理主机的清单，默认是/etc/ansible/hosts文件。</p><h5 id="Modules"><a href="#Modules" class="headerlink" title="Modules"></a>Modules</h5><p>Ansible执行命令的功能模块，Ansible2.3版本为止，共有1039个模块。还可以自定义模块。</p><h5 id="Plugins"><a href="#Plugins" class="headerlink" title="Plugins"></a>Plugins</h5><p>插件，模块功能的补充，常有连接类型插件，循环插件，变量插件，过滤插件，插件功能用的较少。<br>#####API<br>提供给第三方程序调用的应用程序编程接口。</p><h3 id="安装ansible"><a href="#安装ansible" class="headerlink" title="安装ansible"></a>安装ansible</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">yum -y install ansible # 使用yum源安装ansible</span><br><span class="line">ansible --version# 查看ansible版本</span><br></pre></td></tr></table></figure><h4 id="ansible的一般使用"><a href="#ansible的一般使用" class="headerlink" title="ansible的一般使用"></a>ansible的一般使用</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd &#x2F;etc&#x2F;ansible#进入ansible目录下</span><br><span class="line">vim hosts    #修改hosts文件，添加主机组</span><br><span class="line">[组名]     #主机分组的的组名</span><br><span class="line"> IP或者主机名   #被管理主机名</span><br><span class="line"> </span><br><span class="line">ssh-keygen#创建ssh进行ssh免密连接</span><br><span class="line">    （有提示直接根据提示回车或者yes）</span><br><span class="line">    </span><br><span class="line">ssh-copy-id 服务器名(或者用户名@地址)  #给控制服务器复制 ssh秘钥</span><br></pre></td></tr></table></figure><h4 id="常用命令参数"><a href="#常用命令参数" class="headerlink" title="常用命令参数"></a>常用命令参数</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">ansible -h</span><br><span class="line">Usage: ansible &lt;host-group&gt; [options]</span><br><span class="line">-a MODULE_ARGS   #模块参数</span><br><span class="line">-C, --check     #检查语法</span><br><span class="line">-f FORKS        #并发</span><br><span class="line">--list-hosts    #列出主机列表</span><br><span class="line">-m MODULE_NAME  #模块名字</span><br><span class="line">-o              #使用精简的输出</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ansible all --list-hosts#列出所有主机</span><br><span class="line"></span><br><span class="line">ansible all -m ping  &#x2F; ansible 组名 -m ping -kPing所有主机</span><br><span class="line"></span><br><span class="line">ansible &lt;文件名&gt; -m copy -a &#39;src&#x3D;&#x2F;本地路径 dest&#x3D;&#x2F;目标路径&#39;#将本机的&#x2F;etc&#x2F;passwd 复制到远程机子文件 &#x2F;tmp&#x2F;passwd</span><br></pre></td></tr></table></figure><h4 id="Ansible-Ad-hoc模式常用模块"><a href="#Ansible-Ad-hoc模式常用模块" class="headerlink" title="Ansible Ad-hoc模式常用模块"></a>Ansible Ad-hoc模式常用模块</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ping模块、 raw模块、yum模块、apt模块、copy模块、user模块与group模块、、fetch模块、file模块、command 模块和shell</span><br></pre></td></tr></table></figure><p>命令相关模块：command shell<br>    ansible默认的模块,执行命令，注意：shell中的”&lt;”, “&gt;”, “|”, “;”, “&amp;”,”$”等特殊字符不能在command模块中使用，如果需要使用，则用shell模块<br>    shel模块l专门用来执行shell命令的模块，和command模块一样，参数基本一样，</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ansible-doc -s shell# 查看模块参数</span><br></pre></td></tr></table></figure><p>文件相关的模块：file copy<br>    用于对文件的处理，创建，删除，权限控制等</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"> [root@ansible ~]# ansible-doc -s file # 查看模块参数</span><br><span class="line"> path     #要管理的文件路径</span><br><span class="line">   state：</span><br><span class="line">       directory  #创建目录，如果目标不存在则创建目录及其子目录</span><br><span class="line">       touch      #创建文件，如果文件存在，则修改文件 属性</span><br><span class="line">       absent     #删除文件或目录</span><br><span class="line">       mode       #设置文件或目录权限</span><br><span class="line">       owner      #设置文件或目录属主信息</span><br><span class="line">       group      #设置文件或目录属组信息</span><br><span class="line">       </span><br><span class="line">  </span><br><span class="line">  # 创建目录</span><br><span class="line"> [root@ansible ~]# ansible 192.168.1.31 -m file -a &#39;path&#x3D;&#x2F;tmp&#x2F;test1 state&#x3D;directory&#39;</span><br><span class="line"> </span><br><span class="line"> # 创建文件</span><br><span class="line"> [root@ansible ~]# ansible 192.168.1.31 -m file -a &#39;path&#x3D;&#x2F;tmp&#x2F;test2 state&#x3D;touch&#39;</span><br><span class="line"> </span><br><span class="line"> # 删除文件</span><br><span class="line"> [root@ansible ~]# ansible 192.168.1.31 -m file -a &#39;path&#x3D;&#x2F;tmp&#x2F;test2 state&#x3D;absent&#39;</span><br><span class="line"> </span><br><span class="line"> # 创建文件时同时设置权限等信息</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m file -a &#39;path&#x3D;&#x2F;tmp&#x2F;test4 state&#x3D;directory mode&#x3D;775 owner&#x3D;root group&#x3D;root&#39;</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Linux 将访问文件的用户分为 3 类，分别是文件的所有者，所属组（也就是文件所属的群组）以及其他人。</span><br><span class="line">最常见的文件权限有 3 种，即对文件的读（用 r 表示）、 写（用 w 表示）、 执行（用 x 表示，针对可执行文件或目录）权限。</span><br><span class="line">ower     group    other</span><br><span class="line"></span><br><span class="line">r w x    r w x    r w x</span><br><span class="line"></span><br><span class="line">4 2 1    4 2 1    4 2 1 </span><br><span class="line">对于目录来说，常用来设定目录的权限其实只有 0（---）、5（r-x）、7（rwx）这 3 种。</span><br><span class="line"></span><br><span class="line">777 三组都有读写执行权限;  755 所有者读写执行权限  所属组读执行权限  其他人读执行权限</span><br></pre></td></tr></table></figure><h4 id="copy-用于管理端复制文件到远程主机，并可以设置权限，属组，属主等"><a href="#copy-用于管理端复制文件到远程主机，并可以设置权限，属组，属主等" class="headerlink" title="copy 用于管理端复制文件到远程主机，并可以设置权限，属组，属主等"></a>copy 用于管理端复制文件到远程主机，并可以设置权限，属组，属主等</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> [root@ansible ~]# ansible-doc -s copy#查看模块参数</span><br><span class="line"> src      #需要copy的文件的源路径</span><br><span class="line"> dest     #需要copy的文件的目标路径</span><br><span class="line"> backup   #对copy的文件进行备份</span><br><span class="line"></span><br><span class="line"># 复制文件到远程主机并改名</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m copy -a &#39;dest&#x3D;&#x2F;tmp&#x2F;a.sh src&#x3D;&#x2F;root&#x2F;ansible_test.sh&#39; </span><br><span class="line"></span><br><span class="line"># 复制文件到远程主机，并备份远程文件,安装时间信息备份文件（当更新文件内容后，重新copy时用到）</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m copy -a &#39;dest&#x3D;&#x2F;tmp&#x2F;a.sh src&#x3D;&#x2F;root&#x2F;ansible_test.sh backup&#x3D;yes&#39;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="fetch-用于从被管理机器上面拉取文件，拉取下来的内容会保留目录结构，一般情况用在收集被管理机器的日志文件等"><a href="#fetch-用于从被管理机器上面拉取文件，拉取下来的内容会保留目录结构，一般情况用在收集被管理机器的日志文件等" class="headerlink" title="fetch 用于从被管理机器上面拉取文件，拉取下来的内容会保留目录结构，一般情况用在收集被管理机器的日志文件等"></a>fetch 用于从被管理机器上面拉取文件，拉取下来的内容会保留目录结构，一般情况用在收集被管理机器的日志文件等</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">[root@ansible ~]# ansible-doc -s fetch# 查看模块参数</span><br><span class="line">src      #指定需要从远端机器拉取的文件路径</span><br><span class="line">dest     #指定从远端机器拉取下来的文件存放路径</span><br><span class="line"></span><br><span class="line"># 从被管理机器上拉取cron日志文件，默认会已管理节点地址创建一个目录，并存放在内</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m fetch -a &#39;dest&#x3D;&#x2F;tmp src&#x3D;&#x2F;var&#x2F;log&#x2F;cron&#39;</span><br><span class="line"></span><br><span class="line">[root@ansible ~]# tree &#x2F;tmp&#x2F;192.168.1.31&#x2F;</span><br><span class="line">&#x2F;tmp&#x2F;192.168.1.31&#x2F;</span><br><span class="line">└── var</span><br><span class="line">    └── log</span><br><span class="line">        └── cron</span><br><span class="line">directories, 1 file</span><br></pre></td></tr></table></figure><h4 id="软件包相关的模块：-yum"><a href="#软件包相关的模块：-yum" class="headerlink" title="软件包相关的模块： yum"></a>软件包相关的模块： yum</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">[root@ansible ~]# ansible-doc -s yum# 查看模块参数</span><br><span class="line"> name            #指定要操作的软件包名字</span><br><span class="line"> download_dir    #指定下载软件包的存放路径，需要配合download_only一起使用</span><br><span class="line"> download_only   #只下载软件包，而不进行安装，和yum --downloadonly一样</span><br><span class="line"> list:</span><br><span class="line">     installed   #列出所有已安装的软件包</span><br><span class="line">     updates     #列出所有可以更新的软件包</span><br><span class="line">     repos       #列出所有的yum仓库</span><br><span class="line"> state:</span><br><span class="line">     installed, present   #安装软件包(两者任选其一都可以)</span><br><span class="line">     removed, absent      #卸载软件包</span><br><span class="line">     latest      #安装最新软件包</span><br><span class="line"> </span><br><span class="line"># 列出所有已安装的软件包</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m yum -a &#39;list&#x3D;installed&#39;</span><br><span class="line"> </span><br><span class="line"># 列出所有可更新的软件包</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m yum -a &#39;list&#x3D;updates&#39;</span><br><span class="line"></span><br><span class="line">#列出所有的yum仓库</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m yum -a &#39;list&#x3D;repos&#39;</span><br><span class="line"></span><br><span class="line">#只下载软件包并到指定目录下</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m yum -a &#39;name&#x3D;httpd download_only&#x3D;yes download_dir&#x3D;&#x2F;tmp&#39;</span><br><span class="line"> </span><br><span class="line">#安装软件包</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m yum -a &#39;name&#x3D;httpd state&#x3D;installed&#39;</span><br><span class="line"></span><br><span class="line">#卸载软件包</span><br><span class="line">[root@ansible ~]# ansible 192.168.1.31 -m yum -a &#39;name&#x3D;httpd state&#x3D;removed&#39;</span><br></pre></td></tr></table></figure><h3 id="Ansible之Playbook"><a href="#Ansible之Playbook" class="headerlink" title="Ansible之Playbook"></a>Ansible之Playbook</h3><p><code>Playbook</code>与<code>ad-hoc</code>相比,是一种完全不同的运用ansible的方式。<br>    <code>playbook</code>是由一个或多个<code>play</code>组成的列表，<code>play</code>的主要功能在于将事先归并为一组的主机装扮成事先通过<code>ansible</code>中的<code>task</code>定义好的角色。从根本上来讲，所谓的<code>task</code>无非是调用<code>ansible</code>的一个<code>module</code>。将多个<code>play</code>组织在一个<code>playbook</code>中，即可以让它们联合起来按事先编排的机制完成某一任务 </p><h4 id="Playbook核心元素"><a href="#Playbook核心元素" class="headerlink" title="Playbook核心元素"></a>Playbook核心元素</h4><ul><li>Hosts 执行的远程主机列表</li><li>Tasks 任务集</li><li>tags 标签，指定某条任务执行，用于选择运行playbook中的部分代码。</li><li>Varniables 内置变量或自定义变量在playbook中调用</li><li>Templates 模板，即使用模板语法的文件，比如配置文件等</li><li>Handlers 和notity结合使用，由特定条件触发的操作，满足条件方才执行，否则不执行</li></ul><h4 id="Playbook语法"><a href="#Playbook语法" class="headerlink" title="Playbook语法"></a>Playbook语法</h4><p>playbook使用yaml语法格式，后缀可以是yaml,也可以是yml。</p><p>在单一一个playbook文件中，可以连续三个连子号(—)区分多个play。还有选择性的连续三个点好(…)用来表示play的结尾，也可省略。<br>次行开始正常写playbook的内容，一般都会写上描述该playbook的功能。<br>使用#号注释代码。<br>缩进必须统一，不能空格和tab混用。<br>缩进的级别也必须是一致的，同样的缩进代表同样的级别，程序判别配置的级别是通过缩进结合换行实现的。<br>YAML文件内容和Linux系统大小写判断方式保持一致，是区分大小写的，k/v的值均需大小写敏感<br>k/v的值可同行写也可以换行写。同行使用:分隔。<br>v可以是个字符串，也可以是一个列表<br>一个完整的代码块功能需要最少元素包括 name: task</p><h2 id="Playbook的运行方式"><a href="#Playbook的运行方式" class="headerlink" title="Playbook的运行方式"></a>Playbook的运行方式</h2><p>通过<code>ansible-playbook</code>命令运行 格式：<code>ansible-playbook &lt;filename.yml&gt; ... [options]</code> </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">[root@ansible PlayBook]# ansible-playbook -h</span><br><span class="line">#ansible-playbook常用选项：</span><br><span class="line">--check  or -C    #只检测可能会发生的改变，但不真正执行操作</span><br><span class="line">--list-hosts      #列出运行任务的主机</span><br><span class="line">--list-tags       #列出playbook文件中定义所有的tags</span><br><span class="line">--list-tasks      #列出playbook文件中定义的所以任务集</span><br><span class="line">--limit           #主机列表 只针对主机列表中的某个主机或者某个组执行</span><br><span class="line">-f                #指定并发数，默认为5个</span><br><span class="line">-t                #指定tags运行，运行某一个或者多个tags。（前提playbook中有定义tags）</span><br><span class="line">-v                #显示过程  -vv  -vvv更详细</span><br></pre></td></tr></table></figure><h3 id="tasks任务列表"><a href="#tasks任务列表" class="headerlink" title="tasks任务列表"></a>tasks任务列表</h3><p>​    每一个<code>task</code>必须有一个名称<code>name</code>,这样在运行<code>playbook</code>时，从其输出的任务执行信息中可以很清楚的辨别是属于哪一个<code>task</code>的，如果没有定义 <code>name</code>，<code>action</code>的值将会用作输出信息中标记特定的<code>task</code>。 每一个<code>playbook</code>中可以包含一个或者多个<code>tasks</code>任务列表，每一个<code>tasks</code>完成具体的一件事，（任务模块）比如创建一个用户或者安装一个软件等，在<code>hosts</code>中定义的主机或者主机组都将会执行这个被定义的<code>tasks</code>。 </p><h6 id="一个简单的示例"><a href="#一个简单的示例" class="headerlink" title="一个简单的示例"></a>一个简单的示例</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">vim install_apache.yml</span><br><span class="line">---  #固定格式</span><br><span class="line">- hosts: &quot;&#123;&#123;host_group&#125;&#125;&quot;#定义需要执行主机</span><br><span class="line">  vars:</span><br><span class="line">    work_home: &#x2F;home&#x2F;apache&#x2F;packages#设定工作目录</span><br><span class="line">  tasks:#定义一个任务的开始</span><br><span class="line">    - name: add user#定义任务的名称</span><br><span class="line">      tags: useradd</span><br><span class="line">      become: yes</span><br><span class="line">      become_user: root</span><br><span class="line">      become_method: sudo</span><br><span class="line">      user:</span><br><span class="line">        name: &quot;&#123;&#123;user_name&#125;&#125;&quot;</span><br><span class="line">        group: users</span><br><span class="line">        shell: &#x2F;bin&#x2F;bash</span><br><span class="line">        createhome: yes</span><br><span class="line">        home: &#x2F;home&#x2F;&#123;&#123;user_name&#125;&#125;</span><br><span class="line">        state: present</span><br><span class="line">      ignore_errors: yes</span><br><span class="line">    - name: copy install file</span><br><span class="line">      tags: copy</span><br><span class="line">      become: yes</span><br><span class="line">      become_user: root</span><br><span class="line">      become_method: sudo</span><br><span class="line">      shell: cp -arf &#123;&#123;work_home&#125;&#125;&#x2F;httpd-2.4.33 &#123;&#123;work_home&#125;&#125;&#x2F;httpd-2.4.33_&#123;&#123;user_name&#125;&#125;</span><br><span class="line">    - name: compile</span><br><span class="line">      become: yes</span><br><span class="line">      become_user: root</span><br><span class="line">      become_method: sudo</span><br><span class="line">      shell: cd &#123;&#123;work_home&#125;&#125;&#x2F;httpd-2.4.33_&#123;&#123;user_name&#125;&#125; &amp;&amp; .&#x2F;configure --prefix&#x3D;&#x2F;home&#x2F;&#123;&#123;user_name&#125;&#125;&#x2F; --enable-so --enable-mods-shared&#x3D;all --enable-proxy&#x3D;shared --enable-proxy-balancer&#x3D;shared --enable-proxy-http&#x3D;shared --enable-proxy-ajp --enable-deflate --enable-cache --enable-disk-cache --enable-mem-cache --enable-ssl&#x3D;shared --with-ssl&#x3D;&#x2F;usr&#x2F;local&#x2F;ssl&#x2F; --with-apr&#x3D;&#x2F;usr&#x2F;local&#x2F;apr --with-apr-util&#x3D;&#x2F;usr&#x2F;local&#x2F;apr-util &amp;&amp; make clean &amp;&amp; make &amp;&amp; make install</span><br><span class="line">    - name: copy template config file</span><br><span class="line">      tags: config</span><br><span class="line">      become: yes</span><br><span class="line">      become_user: root</span><br><span class="line">      become_method: sudo</span><br><span class="line">      template:</span><br><span class="line">        src: templates&#x2F;httpd-template.conf.j2</span><br><span class="line">        dest: &#x2F;home&#x2F;&#123;&#123;user_name&#125;&#125;&#x2F;conf&#x2F;httpd-&#123;&#123;user_name&#125;&#125;.conf</span><br><span class="line">        owner: &quot;&#123;&#123;user_name&#125;&#125;&quot;</span><br><span class="line">        backup: no</span><br><span class="line">        force: no</span><br><span class="line">        mode: 0755</span><br><span class="line">    - name: grant privileges to user</span><br><span class="line">      tags: grant</span><br><span class="line">      become: yes</span><br><span class="line">      become_user: root</span><br><span class="line">      become_method: sudo</span><br><span class="line">      shell: chown -R &#123;&#123;user_name&#125;&#125;:users &#x2F;home&#x2F;&#123;&#123;user_name&#125;&#125;&#x2F;</span><br><span class="line">    - name: start application</span><br><span class="line">      tags: start</span><br><span class="line">      become: yes</span><br><span class="line">      become_user: root</span><br><span class="line">      become_method: sudo</span><br><span class="line">      shell: su - &#123;&#123;user_name&#125;&#125; -c &quot;httpd -f &#x2F;home&#x2F;&#123;&#123;user_name&#125;&#125;&#x2F;conf&#x2F;httpd-&#123;&#123;user_name&#125;&#125;.conf -k start&quot;</span><br><span class="line">      </span><br><span class="line">      </span><br><span class="line">      ansible-playbook -e &quot;host_group&#x3D;&#123;host_group&#125; user_name&#x3D;&#123;user_name&#125; listen_port&#x3D;&#123;listen_port&#125; server_path&#x3D;&#123;server_path&#125;&quot; install_apache.yml</span><br><span class="line">      </span><br><span class="line">       ansible-playbook -e &quot;&#123;&#39;host_group&#39;:app1 &#39;user_name&#39;:apache1 &#39;listen_port&#39;:8088 &#39;server_path&#39;:app01li&quot; install_apache.yml</span><br></pre></td></tr></table></figure><p>#####执行playbook， 第一次执行可以加-C选项，检查写的playbook是否ok</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">[root@ansible ~]# ansible-playbook playbook01.yml</span><br><span class="line">PLAY [192.168.1.31] *********************************************************************************************</span><br><span class="line">TASK [Gathering Facts] ******************************************************************************************</span><br><span class="line">ok: [192.168.1.31]</span><br><span class="line">TASK [create new file] ******************************************************************************************</span><br><span class="line">changed: [192.168.1.31]</span><br><span class="line">TASK [create new user] ******************************************************************************************</span><br><span class="line">changed: [192.168.1.31]</span><br><span class="line">TASK [install package] ******************************************************************************************</span><br><span class="line">changed: [192.168.1.31]</span><br><span class="line">TASK [config httpd] *********************************************************************************************</span><br><span class="line">changed: [192.168.1.31]</span><br><span class="line">TASK [copy index.html] ******************************************************************************************</span><br><span class="line">changed: [192.168.1.31]</span><br><span class="line">TASK [start httpd] **********************************************************************************************</span><br><span class="line">changed: [192.168.1.31]</span><br><span class="line">PLAY RECAP ******************************************************************************************************</span><br><span class="line">192.168.1.31               : ok&#x3D;7    changed&#x3D;6    unreachable&#x3D;0    failed&#x3D;0    skipped&#x3D;0    rescued&#x3D;0    ignored&#x3D;0 </span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>盘点key value在各个编程语言中的类型</title>
      <link href="golang/key-value/"/>
      <url>golang/key-value/</url>
      
        <content type="html"><![CDATA[<h2 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h2><p>在编程语言中,有这么一种数据类型,我们经常会使用到,他就是类似于json的键值对类型</p><p>那么今天我们就对比一下,在各大编程语言中的key value类型的特点</p><h2 id="main"><a href="#main" class="headerlink" title="main"></a>main</h2><h3 id="python"><a href="#python" class="headerlink" title="python"></a>python</h3><p>key value 叫做字典</p><p>dict类型<br>声明</p><p>字典操作<br>以键值对方式存在的无序数据的组合就是字典</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">方式<span class="number">1</span>：</span><br><span class="line">    变量 = &#123;&#125;</span><br><span class="line"></span><br><span class="line">方式<span class="number">2</span>：</span><br><span class="line">    变量 = <span class="built_in">dict</span>()</span><br></pre></td></tr></table></figure><p>详细信息可以参考<a href="http://victorfengming.gitee.io/course/python_book/%E5%86%85%E7%BD%AE%E5%87%BD%E6%95%B0%E5%8F%8A%E6%93%8D%E4%BD%9C/%E5%AD%97%E5%85%B8.html">这里</a></p><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><p>在Java里面,具有key-value类型的数据为<br>hashmap类型</p><p>HashMap&lt;K,V&gt;：存储数据采用的哈希表结构，元素的存取顺序不能保证一致。由于要保证键的唯一、不重复，需要重写键的hashCode()方法、equals()方法。</p><p>详细信息可以参考<a href="https://victorfengming.gitee.io/blog/note08/">这里</a></p><h3 id="php"><a href="#php" class="headerlink" title="php"></a>php</h3><p>Array 数组 :<br>PHP 中的数组实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型。此类型在很多方面做了优化，因此可以把它当成真正的数组，或列表（向量），散列表（是映射的一种实现），字典，集合，栈，队列以及更多可能性。由于数组元素的值也可以是另一个数组，树形结构和多维数组也是允许的。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$array</span> = <span class="keyword">array</span>(</span><br><span class="line">    <span class="string">&quot;foo&quot;</span> =&gt; <span class="string">&quot;bar&quot;</span>,</span><br><span class="line">    <span class="string">&quot;bar&quot;</span> =&gt; <span class="string">&quot;foo&quot;</span>,</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 自 PHP 5.4 起</span></span><br><span class="line"><span class="variable">$array</span> = [</span><br><span class="line">    <span class="string">&quot;foo&quot;</span> =&gt; <span class="string">&quot;bar&quot;</span>,</span><br><span class="line">    <span class="string">&quot;bar&quot;</span> =&gt; <span class="string">&quot;foo&quot;</span>,</span><br><span class="line">];</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>详细信息可以参考<a href="https://victorfengming.gitee.io/blog/array/#php%E6%95%B0%E7%BB%84">这里</a></p><h3 id="golang"><a href="#golang" class="headerlink" title="golang"></a>golang</h3><p>map是Go中的内置类型，它将一个值与一个键关联起来。可以使用相应的键检索值。</p><p>Map 是一种无序的键值对的集合</p><p>Map 最重要的一点是通过 key 来快速检索数据，key 类似于索引，指向数据的值</p><p>Map 是一种集合，所以我们可以像迭代数组和切片那样迭代它。不过，Map 是无序的，我们无法决定它的返回顺序，这是因为 Map 是使用 hash 表来实现的，也是引用类型</p><p>详细信息可以参考<a href="https://victorfengming.gitee.io/blog/golang-map/">这里</a></p><h3 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h3><p>Map 对象保存键值对，并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。 Map 在涉及频繁增删键值对的场景下会有些性能优势。 </p><p>键的相等(Key equality)<br>键的比较是基于 sameValueZero 算法：<br>NaN 是与 NaN 相等的（虽然 NaN !== NaN），剩下所有其它的值是根据 === 运算符的结果判断是否相等。<br>在目前的ECMAScript规范中，-0和+0被认为是相等的，尽管这在早期的草案中并不是这样。有关详细信息，请参阅浏览器兼容性表中的“Value equality for -0 and 0”。</p><p>详细信息可以参考<a href="https://victorfengming.gitee.io/blog/js-map/">这里</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>golang 中的map类型详解</title>
      <link href="golang/golang-map/"/>
      <url>golang/golang-map/</url>
      
        <content type="html"><![CDATA[<h1 id="一、集合-Map"><a href="#一、集合-Map" class="headerlink" title="一、集合(Map)"></a>一、集合(Map)</h1><h2 id="1-1-什么是Map"><a href="#1-1-什么是Map" class="headerlink" title="1.1 什么是Map"></a>1.1 什么是Map</h2><p>map是Go中的内置类型，它将一个值与一个键关联起来。可以使用相应的键检索值。</p><p>Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据，key 类似于索引，指向数据的值<br>Map 是一种集合，所以我们可以像迭代数组和切片那样迭代它。不过，Map 是无序的，我们无法决定它的返回顺序，这是因为 Map 是使用 hash 表来实现的，也是引用类型</p><p>使用map过程中需要注意的几点： </p><ul><li>map是无序的，每次打印出来的map都会不一样，它不能通过index获取，而必须通过key获取</li><li>map的长度是不固定的，也就是和slice一样，也是一种引用类型</li><li>内置的len函数同样适用于map，返回map拥有的key的数量 </li><li>map的key可以是所有可比较的类型，如布尔型、整数型、浮点型、复杂型、字符串型……也可以键。</li></ul><h2 id="1-2-Map的使用"><a href="#1-2-Map的使用" class="headerlink" title="1.2  Map的使用"></a>1.2  Map的使用</h2><h3 id="1-2-1-使用make-创建map"><a href="#1-2-1-使用make-创建map" class="headerlink" title="1.2.1 使用make()创建map"></a>1.2.1 使用make()创建map</h3><p>可以使用内建函数 make 也可以使用 map 关键字来定义 Map:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 声明变量，默认 map 是 nil */</span></span><br><span class="line"><span class="keyword">var</span> map_variable <span class="keyword">map</span>[key_data_type]value_data_type</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 使用 make 函数 */</span></span><br><span class="line">map_variable = <span class="built_in">make</span>(<span class="keyword">map</span>[key_data_type]value_data_type)</span><br></pre></td></tr></table></figure><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rating := <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">float32</span> &#123;<span class="string">&quot;C&quot;</span>:<span class="number">5</span>, <span class="string">&quot;Go&quot;</span>:<span class="number">4.5</span>, <span class="string">&quot;Python&quot;</span>:<span class="number">4.5</span>, <span class="string">&quot;C++&quot;</span>:<span class="number">2</span> &#125;</span><br></pre></td></tr></table></figure><p>如果不初始化 map，那么就会创建一个 nil map。nil map 不能用来存放键值对</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">   <span class="keyword">var</span> countryCapitalMap <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span></span><br><span class="line">   <span class="comment">/* 创建集合 */</span></span><br><span class="line">   countryCapitalMap = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>)</span><br><span class="line">   </span><br><span class="line">   <span class="comment">/* map 插入 key-value 对，各个国家对应的首都 */</span></span><br><span class="line">   countryCapitalMap[<span class="string">&quot;France&quot;</span>] = <span class="string">&quot;Paris&quot;</span></span><br><span class="line">   countryCapitalMap[<span class="string">&quot;Italy&quot;</span>] = <span class="string">&quot;Rome&quot;</span></span><br><span class="line">   countryCapitalMap[<span class="string">&quot;Japan&quot;</span>] = <span class="string">&quot;Tokyo&quot;</span></span><br><span class="line">   countryCapitalMap[<span class="string">&quot;India&quot;</span>] = <span class="string">&quot;New Delhi&quot;</span></span><br><span class="line">   </span><br><span class="line">   <span class="comment">/* 使用 key 输出 map 值 */</span></span><br><span class="line">   <span class="keyword">for</span> country := <span class="keyword">range</span> countryCapitalMap &#123;</span><br><span class="line">      fmt.Println(<span class="string">&quot;Capital of&quot;</span>,country,<span class="string">&quot;is&quot;</span>,countryCapitalMap[country])</span><br><span class="line">   &#125;</span><br><span class="line">   </span><br><span class="line">   <span class="comment">/* 查看元素在集合中是否存在 */</span></span><br><span class="line">   captial, ok := countryCapitalMap[<span class="string">&quot;United States&quot;</span>]</span><br><span class="line">   <span class="comment">/* 如果 ok 是 true, 则存在，否则不存在 */</span></span><br><span class="line">   <span class="keyword">if</span>(ok)&#123;</span><br><span class="line">      fmt.Println(<span class="string">&quot;Capital of United States is&quot;</span>, captial)  </span><br><span class="line">   &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">      fmt.Println(<span class="string">&quot;Capital of United States is not present&quot;</span>) </span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Capital of France is Paris</span><br><span class="line">Capital of Italy is Rome</span><br><span class="line">Capital of Japan is Tokyo</span><br><span class="line">Capital of India is New Delhi</span><br><span class="line">Capital of United States is not present</span><br></pre></td></tr></table></figure><h3 id="1-2-2-delete-函数"><a href="#1-2-2-delete-函数" class="headerlink" title="1.2.2 delete() 函数"></a>1.2.2 delete() 函数</h3><p>delete(map, key) 函数用于删除集合的元素, 参数为 map 和其对应的 key。删除函数不返回任何值。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;   </span><br><span class="line">   <span class="comment">/* 创建 map */</span></span><br><span class="line">   countryCapitalMap := <span class="keyword">map</span>[<span class="keyword">string</span>] <span class="keyword">string</span> &#123;<span class="string">&quot;France&quot;</span>:<span class="string">&quot;Paris&quot;</span>,<span class="string">&quot;Italy&quot;</span>:<span class="string">&quot;Rome&quot;</span>,<span class="string">&quot;Japan&quot;</span>:<span class="string">&quot;Tokyo&quot;</span>,<span class="string">&quot;India&quot;</span>:<span class="string">&quot;New Delhi&quot;</span>&#125;</span><br><span class="line">   </span><br><span class="line">   fmt.Println(<span class="string">&quot;原始 map&quot;</span>)   </span><br><span class="line">   </span><br><span class="line">   <span class="comment">/* 打印 map */</span></span><br><span class="line">   <span class="keyword">for</span> country := <span class="keyword">range</span> countryCapitalMap &#123;</span><br><span class="line">      fmt.Println(<span class="string">&quot;Capital of&quot;</span>,country,<span class="string">&quot;is&quot;</span>,countryCapitalMap[country])</span><br><span class="line">   &#125;</span><br><span class="line">   </span><br><span class="line">   <span class="comment">/* 删除元素 */</span></span><br><span class="line">   <span class="built_in">delete</span>(countryCapitalMap,<span class="string">&quot;France&quot;</span>);</span><br><span class="line">   fmt.Println(<span class="string">&quot;Entry for France is deleted&quot;</span>)  </span><br><span class="line">   </span><br><span class="line">   fmt.Println(<span class="string">&quot;删除元素后 map&quot;</span>)   </span><br><span class="line">   </span><br><span class="line">   <span class="comment">/* 打印 map */</span></span><br><span class="line">   <span class="keyword">for</span> country := <span class="keyword">range</span> countryCapitalMap &#123;</span><br><span class="line">      fmt.Println(<span class="string">&quot;Capital of&quot;</span>,country,<span class="string">&quot;is&quot;</span>,countryCapitalMap[country])</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">原始 <span class="keyword">map</span></span><br><span class="line">Capital of France is Paris</span><br><span class="line">Capital of Italy is Rome</span><br><span class="line">Capital of Japan is Tokyo</span><br><span class="line">Capital of India is New Delhi</span><br><span class="line">Entry <span class="keyword">for</span> France is deleted</span><br><span class="line">删除元素后 <span class="keyword">map</span></span><br><span class="line">Capital of Italy is Rome</span><br><span class="line">Capital of Japan is Tokyo</span><br><span class="line">Capital of India is New Delhi</span><br></pre></td></tr></table></figure><h3 id="1-2-3-ok-idiom"><a href="#1-2-3-ok-idiom" class="headerlink" title="1.2.3 ok-idiom"></a>1.2.3 ok-idiom</h3><p>我们可以通过key获取map中对应的value值。语法为：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">map</span>[key] </span><br></pre></td></tr></table></figure><p>但是当key如果不存在的时候，我们会得到该value值类型的默认值，比如string类型得到空字符串，int类型得到0。但是程序不会报错。</p><p>所以我们可以使用ok-idiom获取值，可知道key/value是否存在</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">value, ok := <span class="keyword">map</span>[key] </span><br></pre></td></tr></table></figure><p>示例代码：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;fmt&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">m := <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int</span>)</span><br><span class="line">m[<span class="string">&quot;a&quot;</span>] = <span class="number">1</span></span><br><span class="line">x, ok := m[<span class="string">&quot;b&quot;</span>]</span><br><span class="line">fmt.Println(x, ok)</span><br><span class="line">x, ok = m[<span class="string">&quot;a&quot;</span>]</span><br><span class="line">fmt.Println(x, ok)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">0</span> <span class="literal">false</span></span><br><span class="line"><span class="number">1</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><h3 id="1-2-4-map的长度"><a href="#1-2-4-map的长度" class="headerlink" title="1.2.4 map的长度"></a>1.2.4 map的长度</h3><p>使用len函数可以确定map的长度。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">len</span>(<span class="keyword">map</span>)  <span class="comment">// 可以得到map的长度</span></span><br></pre></td></tr></table></figure><h3 id="1-2-5-map是引用类型的"><a href="#1-2-5-map是引用类型的" class="headerlink" title="1.2.5 map是引用类型的"></a>1.2.5 map是引用类型的</h3><p>与切片相似，映射是引用类型。当将映射分配给一个新变量时，它们都指向相同的内部数据结构。因此，一个的变化会反映另一个。</p><p>示例代码：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (  </span><br><span class="line">    <span class="string">&quot;fmt&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;  </span><br><span class="line">    personSalary := <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int</span>&#123;</span><br><span class="line">        <span class="string">&quot;steve&quot;</span>: <span class="number">12000</span>,</span><br><span class="line">        <span class="string">&quot;jamie&quot;</span>: <span class="number">15000</span>,</span><br><span class="line">    &#125;</span><br><span class="line">    personSalary[<span class="string">&quot;mike&quot;</span>] = <span class="number">9000</span></span><br><span class="line">    fmt.Println(<span class="string">&quot;Original person salary&quot;</span>, personSalary)</span><br><span class="line">    newPersonSalary := personSalary</span><br><span class="line">    newPersonSalary[<span class="string">&quot;mike&quot;</span>] = <span class="number">18000</span></span><br><span class="line">    fmt.Println(<span class="string">&quot;Person salary changed&quot;</span>, personSalary)</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Original person salary map[steve:12000 jamie:15000 mike:9000]  </span><br><span class="line">Person salary changed map[steve:12000 jamie:15000 mike:18000] </span><br></pre></td></tr></table></figure><blockquote><p>map不能使用==操作符进行比较。==只能用来检查map是否为空。否则会报错：invalid operation: map1 == map2 (map can only be comparedto nil)</p></blockquote>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JavaScript中的map数据类型</title>
      <link href="front/js/js-map/"/>
      <url>front/js/js-map/</url>
      
        <content type="html"><![CDATA[<h2 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h2><p>　Map是一组键值对的结构，具有极快的查找速度。</p><h3 id="Map的定义"><a href="#Map的定义" class="headerlink" title="Map的定义"></a>Map的定义</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//空map设值key-value</span></span><br><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line">m.set(<span class="string">&quot;XiaoMing&quot;</span>,<span class="number">99</span>);</span><br><span class="line">m.set(<span class="string">&quot;XiaoHong&quot;</span>,<span class="number">66</span>);</span><br><span class="line"><span class="comment">//构造参数传key-value</span></span><br><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>([[<span class="string">&#x27;XiaoMing&#x27;</span>, <span class="number">99</span>], [<span class="string">&#x27;XiaoHong&#x27;</span>, <span class="number">66</span>]]);</span><br></pre></td></tr></table></figure><h3 id="Map中的方法"><a href="#Map中的方法" class="headerlink" title="Map中的方法"></a>Map中的方法</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> <span class="built_in">Set</span>([<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>]);</span><br><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>([[<span class="number">1</span>, <span class="string">&#x27;x&#x27;</span>], [<span class="number">2</span>, <span class="string">&#x27;y&#x27;</span>], [<span class="number">3</span>, <span class="string">&#x27;z&#x27;</span>]]);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> x <span class="keyword">of</span> a) &#123; <span class="comment">// 遍历Array</span></span><br><span class="line">    alert(x);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> x <span class="keyword">of</span> s) &#123; <span class="comment">// 遍历Set</span></span><br><span class="line">    alert(x);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> x <span class="keyword">of</span> m) &#123; <span class="comment">// 遍历Map</span></span><br><span class="line">    alert(x[<span class="number">0</span>] + <span class="string">&#x27;=&#x27;</span> + x[<span class="number">1</span>]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="更好的遍历：forEach"><a href="#更好的遍历：forEach" class="headerlink" title="更好的遍历：forEach"></a>更好的遍历：forEach</h3><p>　forEach是iterable内置的方法，它接收一个函数，每次迭代就自动回调该函数。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>];</span><br><span class="line">a.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">element, index, array</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// element: 指向当前元素的值</span></span><br><span class="line">    <span class="comment">// index: 指向当前索引</span></span><br><span class="line">    <span class="comment">// array: 指向Array对象本身</span></span><br><span class="line">    alert(element);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Set与Array类似，但Set没有索引，因此回调函数的前两个参数都是元素本身：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> <span class="built_in">Set</span>([<span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>]);</span><br><span class="line">s.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">element, sameElement, set</span>) </span>&#123;</span><br><span class="line">    alert(element);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Map的回调函数参数依次为value、key和map本身：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>([[<span class="number">1</span>, <span class="string">&#x27;x&#x27;</span>], [<span class="number">2</span>, <span class="string">&#x27;y&#x27;</span>], [<span class="number">3</span>, <span class="string">&#x27;z&#x27;</span>]]);</span><br><span class="line">m.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">value, key, map</span>) </span>&#123;</span><br><span class="line">    alert(value);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Golang web编程服务端 客户端爬虫</title>
      <link href="golang/note/golang-server/"/>
      <url>golang/note/golang-server/</url>
      
        <content type="html"><![CDATA[<h3 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;fmt&quot;</span></span><br><span class="line"><span class="string">&quot;net/http&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// w 用于给客户端回复数据</span></span><br><span class="line"><span class="comment">// request ,读取客户端发送的数据</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">HandConn</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">w.Write([]<span class="keyword">byte</span>(<span class="string">&quot;hello go net server&quot;</span>))</span><br><span class="line"><span class="comment">// 给客户端回复数据</span></span><br><span class="line">fmt.Println(r)</span><br><span class="line">fmt.Println(<span class="string">&quot;r.Method&quot;</span>,r.Method)</span><br><span class="line">fmt.Println(<span class="string">&quot;r.Body&quot;</span>,r.Body)</span><br><span class="line">fmt.Println(<span class="string">&quot;r.Header&quot;</span>,r.Header)</span><br><span class="line">fmt.Println(<span class="string">&quot;r.Url&quot;</span>,r.URL)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span>  &#123;</span><br><span class="line"><span class="comment">// 注册处理函数,用户连接,自动调用指定的处理函数</span></span><br><span class="line">http.HandleFunc(<span class="string">&quot;/&quot;</span>,HandConn)</span><br><span class="line"><span class="comment">// 监听绑定</span></span><br><span class="line">http.ListenAndServe(<span class="string">&quot;:8000&quot;</span>,<span class="literal">nil</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h3><h4 id="普通版爬虫"><a href="#普通版爬虫" class="headerlink" title="普通版爬虫"></a>普通版爬虫</h4><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;fmt&quot;</span></span><br><span class="line"><span class="string">&quot;net/http&quot;</span></span><br><span class="line"><span class="string">&quot;os&quot;</span></span><br><span class="line"><span class="string">&quot;strconv&quot;</span></span><br><span class="line">)</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">doWork</span><span class="params">(start, end <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">ori_url := <span class="string">&quot;https://tieba.baidu.com/f?kw=%E7%A9%BF%E8%B6%8A%E7%81%AB%E7%BA%BF&amp;ie=utf-8&amp;pn=&quot;</span></span><br><span class="line"><span class="keyword">for</span> i := start; i&lt;= end ; i++ &#123;</span><br><span class="line">url := ori_url+strconv.Itoa((i<span class="number">-1</span>)*<span class="number">50</span>)</span><br><span class="line">result, err := doSpider(url)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;doSpider error = &quot;</span>,err)</span><br><span class="line"><span class="keyword">continue</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*把内容写入到文件*/</span></span><br><span class="line"><span class="comment">//以这个i为文件名</span></span><br><span class="line">fileName := strconv.Itoa(i) + <span class="string">&quot;.html&quot;</span></span><br><span class="line">f, err1 := os.Create(fileName)</span><br><span class="line"><span class="keyword">if</span> err1 != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;os.Create err1 = &quot;</span>,err1)</span><br><span class="line"><span class="keyword">continue</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 写内容</span></span><br><span class="line">f.WriteString(result)</span><br><span class="line"><span class="comment">//关闭文件</span></span><br><span class="line">f.Close()</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">doSpider</span><span class="params">(url <span class="keyword">string</span>)</span> <span class="params">(result <span class="keyword">string</span>, err error)</span></span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;当前准备爬取&gt;&gt;&gt;&gt;&quot;</span>,url)</span><br><span class="line">resp, err := http.Get(url)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;http.Get = &quot;</span>,err)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line"></span><br><span class="line"><span class="comment">//fmt.Println(&quot;status = &quot;,resp.Status)</span></span><br><span class="line"><span class="comment">//fmt.Println(&quot;status = &quot;,resp.StatusCode)</span></span><br><span class="line"><span class="comment">//fmt.Println(&quot;status = &quot;,resp.Header)</span></span><br><span class="line"><span class="comment">//fmt.Println(&quot;status = &quot;,resp.Body)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*读取网页body内容*/</span></span><br><span class="line">buf := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">4</span>*<span class="number">1024</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>&#123;</span><br><span class="line">n, err := resp.Body.Read(buf)</span><br><span class="line"><span class="keyword">if</span> n == <span class="number">0</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;read err = &quot;</span>, err)</span><br><span class="line"><span class="keyword">break</span></span><br><span class="line">&#125;</span><br><span class="line">result += <span class="keyword">string</span>(buf[:n])</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> start, end <span class="keyword">int</span></span><br><span class="line">fmt.Println(<span class="string">&quot;请输入start页码(&gt;1):&quot;</span>)</span><br><span class="line">fmt.Scan(&amp;start)</span><br><span class="line">fmt.Println(<span class="string">&quot;请输入end页码:&quot;</span>)</span><br><span class="line">fmt.Scan(&amp;end)</span><br><span class="line">doWork(start,end)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="并发爬虫"><a href="#并发爬虫" class="headerlink" title="并发爬虫"></a>并发爬虫</h4><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;fmt&quot;</span></span><br><span class="line"><span class="string">&quot;net/http&quot;</span></span><br><span class="line"><span class="string">&quot;os&quot;</span></span><br><span class="line"><span class="string">&quot;strconv&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">spiderPage</span><span class="params">(i <span class="keyword">int</span>, page <span class="keyword">chan</span>&lt;- <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;正在爬第&quot;</span>,i,<span class="string">&quot;个网页&gt;&gt;&gt;&gt;&gt;&quot;</span>)</span><br><span class="line">ori_url := <span class="string">&quot;https://tieba.baidu.com/f?kw=%E7%A9%BF%E8%B6%8A%E7%81%AB%E7%BA%BF&amp;ie=utf-8&amp;pn=&quot;</span></span><br><span class="line">url := ori_url + strconv.Itoa((i<span class="number">-1</span>)*<span class="number">50</span>)</span><br><span class="line">result, err := doSpider(url)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;doSpider error = &quot;</span>, err)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*把内容写入到文件*/</span></span><br><span class="line"><span class="comment">//以这个i为文件名</span></span><br><span class="line">fileName := strconv.Itoa(i) + <span class="string">&quot;.html&quot;</span></span><br><span class="line">f, err1 := os.Create(fileName)</span><br><span class="line"><span class="keyword">if</span> err1 != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;os.Create err1 = &quot;</span>, err1)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 写内容</span></span><br><span class="line">f.WriteString(result)</span><br><span class="line"><span class="comment">//关闭文件</span></span><br><span class="line">f.Close()</span><br><span class="line"></span><br><span class="line">page &lt;- i</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">doWork</span><span class="params">(start, end <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">page := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"><span class="keyword">for</span> i := start; i &lt;= end; i++ &#123;</span><br><span class="line"><span class="keyword">go</span> spiderPage(i,page)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> i := start; i &lt;= end; i++ &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;第%d个页面爬取完成&quot;</span>,&lt;-page)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">doSpider</span><span class="params">(url <span class="keyword">string</span>)</span> <span class="params">(result <span class="keyword">string</span>, err error)</span></span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;当前准备爬取&gt;&gt;&gt;&gt;&quot;</span>, url)</span><br><span class="line">resp, err := http.Get(url)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;http.Get = &quot;</span>, err)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line"></span><br><span class="line"><span class="comment">//fmt.Println(&quot;status = &quot;,resp.Status)</span></span><br><span class="line"><span class="comment">//fmt.Println(&quot;status = &quot;,resp.StatusCode)</span></span><br><span class="line"><span class="comment">//fmt.Println(&quot;status = &quot;,resp.Header)</span></span><br><span class="line"><span class="comment">//fmt.Println(&quot;status = &quot;,resp.Body)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*读取网页body内容*/</span></span><br><span class="line">buf := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">4</span>*<span class="number">1024</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line">n, err := resp.Body.Read(buf)</span><br><span class="line"><span class="keyword">if</span> n == <span class="number">0</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;read err = &quot;</span>, err)</span><br><span class="line"><span class="keyword">break</span></span><br><span class="line">&#125;</span><br><span class="line">result += <span class="keyword">string</span>(buf[:n])</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> start, end <span class="keyword">int</span></span><br><span class="line">fmt.Println(<span class="string">&quot;请输入start页码(&gt;1):&quot;</span>)</span><br><span class="line">fmt.Scan(&amp;start)</span><br><span class="line">fmt.Println(<span class="string">&quot;请输入end页码:&quot;</span>)</span><br><span class="line">fmt.Scan(&amp;end)</span><br><span class="line">doWork(start, end)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Golang学习笔记01</title>
      <link href="golang/note/golang-note1/"/>
      <url>golang/note/golang-note1/</url>
      
        <content type="html"><![CDATA[<p>在go语言的main()函数外面是不能记性语句的执行的,只能写一些定义的语句</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">&quot;fmt&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">/*if 变体 这个num 这能够在 if else 中使用 ,作用范围固定了*/</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> num := <span class="number">10</span>; num % <span class="number">2</span> == <span class="number">0</span> &#123; <span class="comment">//checks if number is even</span></span><br><span class="line">        fmt.Println(num,<span class="string">&quot;is even&quot;</span>)</span><br><span class="line">    &#125;  <span class="keyword">else</span> &#123;</span><br><span class="line">        fmt.Println(num,<span class="string">&quot;is odd&quot;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/*go 中的复制是深拷贝,不存在引用传递的问题*/</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    a := [...]<span class="keyword">string</span>&#123;<span class="string">&quot;USA&quot;</span>, <span class="string">&quot;China&quot;</span>, <span class="string">&quot;India&quot;</span>, <span class="string">&quot;Germany&quot;</span>, <span class="string">&quot;France&quot;</span>&#125;</span><br><span class="line">    b := a <span class="comment">// a copy of a is assigned to b</span></span><br><span class="line">    b[<span class="number">0</span>] = <span class="string">&quot;Singapore&quot;</span></span><br><span class="line">    fmt.Println(<span class="string">&quot;a is &quot;</span>, a)</span><br><span class="line">    fmt.Println(<span class="string">&quot;b is &quot;</span>, b)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>map集合就像python中的字典<br>delete(map, key) 函数用于删除集合的元素, 参数为 map 和其对应的 key。删除函数不返回任何值。</p><p>取值,并且判断是否存在</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">&quot;fmt&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    m := <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int</span>)</span><br><span class="line">    m[<span class="string">&quot;a&quot;</span>] = <span class="number">1</span></span><br><span class="line">    x, ok := m[<span class="string">&quot;b&quot;</span>]</span><br><span class="line">    fmt.Println(x, ok)</span><br><span class="line">    x, ok = m[<span class="string">&quot;a&quot;</span>]</span><br><span class="line">    fmt.Println(x, ok)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>go中的map是引用类型,如果赋值到其他变量后,会同步更改值</p><p>go中的结构体,就像Java中的工厂类</p><p>结构体的匿名字段就类似类的继承</p><p>接口,结构体,方法</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*定义接口*/</span></span><br><span class="line"><span class="keyword">type</span> myInterface <span class="keyword">interface</span> &#123;</span><br><span class="line">add()</span><br><span class="line">remove()</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">type</span> MyS <span class="keyword">struct</span> &#123;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(MyS)</span> <span class="title">add</span><span class="params">()</span></span>&#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;MyS增加&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(MyS)</span> <span class="title">remove</span><span class="params">()</span></span>&#123;</span><br><span class="line">fmt.Println(<span class="string">&quot;mys删除&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">var</span> myf myInterface</span><br><span class="line">myf = <span class="built_in">new</span>(MyS)</span><br><span class="line">myf.add()</span><br><span class="line">myf.remove()</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在go中<br>接口进行实例化,然后这个变量能够存储一个结构体的实例化对象,并且这个结构体有对应的实现的方法,这个方法之前在这个接口中声明过,然后就成了</p><p>虽然method的名字一模一样，但是如果接收者不一样，那么method就不一样</p><p>method里面可以访问接收者的字段</p><p>调用method通过.访问，就像struct里面访问字段一样</p><p>type是go语法里的重要而且常用的关键字，type绝不只是对应于C/C++中的typedef。搞清楚type的使用，就容易理解go语言中的核心概念struct、interface、函数等的使用</p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue如何使用G2绘制图片</title>
      <link href="front/vue/vue-g2/"/>
      <url>front/vue/vue-g2/</url>
      
        <content type="html"><![CDATA[<h2 id="使用vue-cli创建项目"><a href="#使用vue-cli创建项目" class="headerlink" title="使用vue cli创建项目"></a>使用vue cli创建项目</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 全局安装脚手架</span><br><span class="line">npm install -g @vue&#x2F;cli-init</span><br><span class="line"># 初始化项目</span><br><span class="line">vue init webpack-simple my-g2-study</span><br><span class="line"># 进入目录</span><br><span class="line">cd my-g2-study</span><br><span class="line"># 安装g2依赖</span><br><span class="line">yarn add @antv&#x2F;g2</span><br></pre></td></tr></table></figure><h2 id="项目启动"><a href="#项目启动" class="headerlink" title="项目启动"></a>项目启动</h2><p>首先使用下面启动项目</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn run serve</span><br></pre></td></tr></table></figure><p>然后使用webstorm打开项目目录，我们需要在components下，创建一个文件HelloG2.vue</p><h3 id="引用G2包"><a href="#引用G2包" class="headerlink" title="引用G2包"></a>引用G2包</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import G2 from &#39;@antv&#x2F;g2&#39;;</span><br></pre></td></tr></table></figure><h3 id="创建div图表容器"><a href="#创建div图表容器" class="headerlink" title="创建div图表容器"></a>创建div图表容器</h3><p>我们需要在页面的body部分创建一个div，然后设置id</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;div id&#x3D;&quot;c1&quot;&gt;&lt;&#x2F;div&gt;</span><br></pre></td></tr></table></figure><h3 id="编写图表绘制代码"><a href="#编写图表绘制代码" class="headerlink" title="编写图表绘制代码"></a>编写图表绘制代码</h3><p>创建 <code>div</code> 容器后，我们就可以进行简单的图表绘制，主要分为下面几步：</p><ol><li>创建 Chart 图表对象，指定图表所在的容器 ID、指定图表的宽高、边距等信息；</li><li>载入图表数据源；</li><li>使用图形语法进行图表的绘制；</li><li>渲染图表</li></ol><p>完整代码如下所示：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div id&#x3D;&quot;c1&quot;&gt;&lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">    import G2 from &#39;@antv&#x2F;g2&#39;;</span><br><span class="line"></span><br><span class="line">    export default &#123;</span><br><span class="line">        name: &#39;HelloG2&#39;,</span><br><span class="line">        props: &#123;</span><br><span class="line">            msg: String</span><br><span class="line">        &#125;,</span><br><span class="line">        mounted() &#123;</span><br><span class="line">            const data &#x3D; [</span><br><span class="line">                &#123;genre: &#39;Sports&#39;, sold: 275&#125;,</span><br><span class="line">                &#123;genre: &#39;Strategy&#39;, sold: 115&#125;,</span><br><span class="line">                &#123;genre: &#39;Action&#39;, sold: 120&#125;,</span><br><span class="line">                &#123;genre: &#39;Shooter&#39;, sold: 350&#125;,</span><br><span class="line">                &#123;genre: &#39;Other&#39;, sold: 150&#125;,</span><br><span class="line">            ];</span><br><span class="line">            &#x2F;&#x2F; G2 对数据源格式的要求，仅仅是 JSON 数组，数组的每个元素是一个标准 JSON 对象。</span><br><span class="line"></span><br><span class="line">            &#x2F;&#x2F; Step 1: 创建 Chart 对象</span><br><span class="line">            const chart &#x3D; new G2.Chart(&#123;</span><br><span class="line">                container: &#39;c1&#39;,</span><br><span class="line">                width: 600,</span><br><span class="line">                height: 300,</span><br><span class="line">            &#125;);</span><br><span class="line"></span><br><span class="line">            &#x2F;&#x2F; Step 2: 载入数据源</span><br><span class="line">            chart.source(data);</span><br><span class="line"></span><br><span class="line">            &#x2F;&#x2F; Step 3：创建图形语法，绘制柱状图，由 genre 和 sold 两个属性决定图形位置，genre 映射至 x 轴，sold 映射至 y 轴</span><br><span class="line">            chart</span><br><span class="line">                .interval()</span><br><span class="line">                .position(&#39;genre*sold&#39;)</span><br><span class="line">                .color(&#39;genre&#39;);</span><br><span class="line"></span><br><span class="line">            &#x2F;&#x2F; Step 4: 渲染图表</span><br><span class="line">            chart.render();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- Add &quot;scoped&quot; attribute to limit CSS to this component only --&gt;</span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;style&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>然后在App.vue引用该组件即可</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div id&#x3D;&quot;app&quot;&gt;</span><br><span class="line">    &lt;HelloG2 msg&#x3D;&quot;Welcome to Your Vue.js App&quot;&#x2F;&gt;</span><br><span class="line">  &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">import HelloG2 from &#39;.&#x2F;components&#x2F;HelloG2.vue&#39;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line">  name: &#39;app&#39;,</span><br><span class="line">  components: &#123;</span><br><span class="line">    HelloG2</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style&gt;</span><br><span class="line">#app &#123;</span><br><span class="line">  font-family: &#39;Avenir&#39;, Helvetica, Arial, sans-serif;</span><br><span class="line">  -webkit-font-smoothing: antialiased;</span><br><span class="line">  -moz-osx-font-smoothing: grayscale;</span><br><span class="line">  text-align: center;</span><br><span class="line">  color: #2c3e50;</span><br><span class="line">  margin-top: 60px;</span><br><span class="line">&#125;</span><br><span class="line">&lt;&#x2F;style&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>最后效果图：</p><p><img src= "/img/loading.gif" data-lazy-src="image-20191222163912882.png" alt="image-20191222163912882"></p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> front </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>各种解决方案汇总</title>
      <link href="unclass/task/"/>
      <url>unclass/task/</url>
      
        <content type="html"><![CDATA[<h1 id="链接汇总"><a href="#链接汇总" class="headerlink" title="链接汇总"></a>链接汇总</h1><h3 id="20200305"><a href="#20200305" class="headerlink" title="20200305"></a>20200305</h3><hr><ul><li>博客园: <a href="https://www.jianshu.com/p/fbd1ba0a7ce7">FastAPI框架快速构建高性能的api服务</a></li><li>简书: <a href="https://www.jianshu.com/p/94710ed35b92">fastapi教程翻译(一)：了解FastAPI结构</a></li><li>简书: <a href="https://www.jianshu.com/p/fbd1ba0a7ce7">HTTP request : Content-Type</a></li><li>博客园: <a href="https://www.cnblogs.com/wushifeng/p/6707248.html">四种常见的 POST 提交数据方式对应的content-type取值</a></li><li>开源中国: <a href="https://tool.oschina.net/commons">常用对照表</a></li><li>菜鸟教程: <a href="https://www.runoob.com/docker/docker-tutorial.html">基于go的容器docker</a></li></ul><hr><ul><li>博客园: <a href="https://www.cnblogs.com/sunyuhuan/p/7280085.html">F5与Nginx的区别</a></li><li>博客园: <a href="https://www.cnblogs.com/biningooginind/p/12388467.html">一款属于自己的笔记本【vue+gin+elementUI前后端分离开发部署开源项目】</a></li></ul><h3 id="20200306"><a href="#20200306" class="headerlink" title="20200306"></a>20200306</h3><hr><ul><li>CSDN: <a href="https://blog.csdn.net/LJFPHP/article/details/83545958">vue中监听input框获取焦点，失去焦点的问题</a></li><li>简书: <a href="https://www.jianshu.com/p/168530ded423">绑定数据变量</a></li><li>CSDN: <a href="https://blog.csdn.net/u012153741/article/details/65442379">f5 负载均衡初识与配置</a></li></ul><h3 id="20200307"><a href="#20200307" class="headerlink" title="20200307"></a>20200307</h3><hr><ul><li>博客园: <a href="https://www.cnblogs.com/wangyingblock/p/11905220.html">python开发F5相关功能</a></li><li>CSDN: <a href="https://blog.csdn.net/blackawhite/article/details/79644279">F5（负载均衡）使用配置文档</a></li><li>官方文档: <a href="https://f5-sdk.readthedocs.io/en/latest/apidoc/modules.html">F5-SDK</a></li><li>官方文档: <a href="https://f5-sdk.readthedocs.io/en/latest/_modules/f5/bigip.html#ManagementRoot">F5 Python SDK</a></li></ul><hr><ul><li>CSDN: <a href="https://blog.csdn.net/nicewuranran/article/details/52860769">浅谈服务器集群、负载均衡、与分布式</a></li></ul><h3 id="20200316"><a href="#20200316" class="headerlink" title="20200316"></a>20200316</h3><hr><ul><li>W3C: <a href="https://www.w3cschool.cn/http/yerxcfmt.html">HTTP 请求方法</a></li></ul><hr><h1 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h1><h2 id="需求0"><a href="#需求0" class="headerlink" title="需求0"></a>需求0</h2><p>mssql中的login_sid 乱码问题</p><h2 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h2><p>数据库中就乱码了,需要验证在django后台存储时的问题,还是远端服务器中读取数据本身就是乱码了.</p><h2 id="需求1"><a href="#需求1" class="headerlink" title="需求1"></a>需求1</h2><p>当用户输入完,id 的数据时,自动填充下面两个input输入框中对应的内容,由于是管理员操作界面,所以自动填充的内容还可以进行更改</p><h2 id="实现步骤"><a href="#实现步骤" class="headerlink" title="实现步骤"></a>实现步骤</h2><ol start="0"><li><p>需要自动添加的vue-input中的内容<a href="https://www.jianshu.com/p/168530ded423">绑定数据变量</a><br><code>v-bind</code></p></li><li><p>Vue(js),<a href="https://blog.csdn.net/LJFPHP/article/details/83545958">vue中监听input框获取焦点，失去焦点的问题</a></p></li><li><p>触发对应函数,发送ajax请求</p></li><li><p>在请求中,访问对应查询接口(需要携带用户输入的参数)</p></li><li><p>django端处理,通过对数据库的查询进行结果的返回(json)</p><p> 如果查询失败,返回对应状态码</p></li><li><p>js(vue)端接收数据,解析数据</p><ul><li>成功,走第7条</li><li>失败,pass</li></ul></li><li><p>赋值到之前定义好的绑定的数据变量中,</p></li></ol><h2 id="需求2"><a href="#需求2" class="headerlink" title="需求2"></a>需求2</h2><p>用户通过下拉框实现选择某条记录后,表单中下面两个对应的input中的内容自动填充,由于是管理员操作界面,所以自动填充的内容还可以进行更改</p><h2 id="分析-1"><a href="#分析-1" class="headerlink" title="分析"></a>分析</h2><ol start="0"><li><p>在需要自动填充的input框下<a href="https://www.jianshu.com/p/168530ded423">绑定数据变量</a></p></li><li><p>表单加载成功后,自动去调用对应接口</p></li><li><p>django 处理,查询数据,并返回</p></li><li><p>js(vue)接收数据,并赋值到绑定的变量中</p></li><li><p>自动添加的vue-input中的内容<a href="https://www.jianshu.com/p/168530ded423">绑定数据变量</a><br><code>v-bind</code></p></li><li><p>Vue(js)端添加监听鼠标失去焦点事件,<a href="https://blog.csdn.net/LJFPHP/article/details/83545958">vue中监听input框获取焦点，失去焦点的问题</a></p></li><li><p>触发对应函数,发送ajax请求</p></li><li><p>在请求中,访问对应查询接口(需要携带用户输入的参数)</p></li><li><p>django端处理,通过对数据库的查询进行结果的返回(json)</p><p> 如果查询失败,返回对应状态码</p></li><li><p>js(vue)端接收数据,解析数据</p><ul><li>成功,走第7条</li><li>失败,pass</li></ul></li><li><p>赋值到之前定义好的绑定的数据变量中,</p></li></ol><h2 id="需求3"><a href="#需求3" class="headerlink" title="需求3"></a>需求3</h2><p>DataBase Oracle中的 Oracle Application<br>查询搜索条件  role 中分为 owner 和 admin<br>需要在加上这个列的表格后能够通过本列的条件进行搜索  </p><h2 id="分析-2"><a href="#分析-2" class="headerlink" title="分析"></a>分析</h2><p>在这个原有的功能中,加上一条判断</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">role = request.GET.get(<span class="string">&quot;role&quot;</span>)</span><br><span class="line"><span class="comment"># 然后在重新写一个SQL语句,加上where role = %s</span></span><br></pre></td></tr></table></figure><h2 id="f5负载均衡"><a href="#f5负载均衡" class="headerlink" title="f5负载均衡"></a>f5负载均衡</h2><p>python配置f5</p><ul><li>博客园: <a href="https://www.cnblogs.com/wangyingblock/p/11905220.html">python开发F5相关功能</a></li><li>CSDN: <a href="https://blog.csdn.net/blackawhite/article/details/79644279">F5（负载均衡）使用配置文档</a></li><li>官方文档: <a href="https://f5-sdk.readthedocs.io/en/latest/apidoc/modules.html">F5-SDK</a></li><li>官方文档: <a href="https://f5-sdk.readthedocs.io/en/latest/_modules/f5/bigip.html#ManagementRoot">F5 Python SDK</a></li></ul><h2 id="elk"><a href="#elk" class="headerlink" title="elk"></a>elk</h2><p><a href="https://my.oschina.net/itblog/blog/547250/">ELK(ElasticSearch, Logstash, Kibana)搭建实时日志分析平台</a></p><p><a href="https://www.cnblogs.com/aresxin/p/8035137.html">ELK原理与介绍</a></p><h2 id="Apache-app分析"><a href="#Apache-app分析" class="headerlink" title="Apache_app分析"></a>Apache_app分析</h2><p>根据app_f5中参考</p><h3 id="路由-视图函数"><a href="#路由-视图函数" class="headerlink" title="路由/视图函数"></a>路由/视图函数</h3><ol start="0"><li>获取信息并存储到数据库中</li><li>显示主界面<ol start="0"><li>增: post()方法</li><li>删: delete()方法</li><li>改: put()方法</li><li>查: get()方法</li></ol></li></ol><h3 id="视图函数步骤"><a href="#视图函数步骤" class="headerlink" title="视图函数步骤"></a>视图函数步骤</h3><p>通过被调用的请求参数request获取前端页面中传递过来的参数</p><p>连接数据库(调用settings中数据库的常量)</p><p>拼接SQL语句(选择要查询出来的字段,加上需要的限制条件,对结果进行排序)</p><p>根据不同的方法中的不同功能对数据库进行响应的操作(主要的业业务逻辑)</p><p>获取执行结果</p><p>返回response信息(try…catch包裹)</p><p>如果有异常,返回对应的报错信息</p><h3 id="目前的进度"><a href="#目前的进度" class="headerlink" title="目前的进度"></a>目前的进度</h3><p>新建一个git分支(branch),web_ioms_apache</p><p>在apps文件夹中,创建一个新的django-app</p><p>在settings配置文件中,加入install app 中</p><p>在app_apache中,创建文件urls.py</p><p>在IOMS文件夹中的总路由文件urls.py中配置字路由</p><p>写两个路由:获取信息,显示 主界面的</p><p>创建对应路由的类,并继承APIView</p><p>由于接口字段不确定,所以获取字段的部分不能写完整</p><p>封装了两个方法,写了一个显示主界面的一个类,其中有post(), delete(), put(), get(), 方法,对应着不同的逻辑,同一个接口路由,请求方式不同,调用的函数不同</p>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> solution </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>了解FastAPI结构</title>
      <link href="python/fastapi-introduce/"/>
      <url>python/fastapi-introduce/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.jianshu.com/p/94710ed35b92">https://www.jianshu.com/p/94710ed35b92</a></p><h2>一、编写一个简单的FastAPI程序</h2><p>最简单的FastAPI文件可能如下：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI<p>app <span class="token operator">=</span> FastAPI<span class="token punctuation">(</span><span class="token punctuation">)</span></p><p>@app<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">“/“</span><span class="token punctuation">)</span><br><span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">root</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span><span class="token string">“message”</span><span class="token punctuation">:</span> <span class="token string">“Hello World”</span><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><p>将上面代码块复制到 <code>main.py</code>.</p><p>启动服务：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-css"><code class="  language-css">uvicorn <span class="token property">main</span><span class="token punctuation">:</span>app --reload<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p><strong>注意：</strong></p><p><code>uvicorn main:app</code> 命令指:</p><ul><li><code>main</code>: <code>main.py</code> 文件(也可理解为Python模块).</li><li><code>app</code>: <code>main.py</code> 中<code>app = FastAPI()</code>语句创建的app对象.</li><li><code>--reload</code>: 在代码改变后重启服务器，只能在开发的时候使用</li></ul><p>你将会看到如下的输出：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-csharp"><code class="  language-csharp">INFO<span class="token punctuation">:</span> <span class="token class-name">Started</span> reloader process <span class="token punctuation">[</span><span class="token number">17961</span><span class="token punctuation">]</span>INFO<span class="token punctuation">:</span> <span class="token class-name">Started</span> server process <span class="token punctuation">[</span><span class="token number">17962</span><span class="token punctuation">]</span>INFO<span class="token punctuation">:</span> <span class="token class-name">Waiting</span> <span class="token keyword">for</span> application startup<span class="token punctuation">.</span>INFO<span class="token punctuation">:</span> <span class="token class-name">Uvicorn</span> running on http<span class="token punctuation">:</span><span class="token operator">/</span><span class="token operator">/</span><span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span><span class="token punctuation">:</span><span class="token number">8000</span> <span class="token punctuation">(</span><span class="token class-name">Press</span> CTRL<span class="token operator">+</span><span class="token class-name">C</span> to quit<span class="token punctuation">)</span> <span class="token operator">&lt;</span><span class="token operator">/</span>pre<span class="token operator">&gt;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div><p>最后一句表明你的app服务在本地的URL地址。</p><h2>二、检查</h2><p>打开你的浏览器，输入 <a href="https://links.jianshu.com/go?to=http%3A%2F%2F127.0.0.1%3A8000%2F" target="_blank">http://127.0.0.1:8000</a>.</p><p>你将会看见JSON响应：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-json"><code class="  language-json"><span class="token punctuation">&#123;</span><span class="token property">"hello"</span><span class="token operator">:</span> <span class="token string">"world"</span><span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><h2>三、API交互文档</h2><p>现在转到 <a href="https://links.jianshu.com/go?to=http%3A%2F%2F127.0.0.1%3A8000%2Fdocs" target="_blank">http://127.0.0.1:8000/docs</a>.</p><p>你将会看到自动生成的API交互文档(由 <a href="https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fswagger-api%2Fswagger-ui" target="_blank">Swagger UI</a>提供):<br></p><div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 788px; background-color: transparent;"><div class="image-container-fill" style="padding-bottom: 112.5%;"></div><div class="image-view" data-width="960" data-height="1080"><img data-original-src="//upload-images.jianshu.io/upload_images/12745724-93152ffa97ca22b2.png" data-original-width="960" data-original-height="1080" data-original-format="image/png" data-original-filesize="94592" data-image-index="0" style="cursor: zoom-in;" class="" src= "/img/loading.gif" data-lazy-src="//upload-images.jianshu.io/upload_images/12745724-93152ffa97ca22b2.png?imageMogr2/auto-orient/strip|imageView2/2/w/960/format/webp"></div></div><div class="image-caption"></div></div><p></p><h2>四、可选的API文档</h2><p>现在，转到 <a href="https://links.jianshu.com/go?to=http%3A%2F%2F127.0.0.1%3A8000%2Fredoc" target="_blank">http://127.0.0.1:8000/redoc</a>.</p><p>你将会看到自动生成的可选的API文档(由(provided by <a href="https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2FRebilly%2FReDoc" target="_blank">ReDoc</a>提供):</p><div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 788px; background-color: transparent;"><div class="image-container-fill" style="padding-bottom: 112.5%;"></div><div class="image-view" data-width="960" data-height="1080"><img data-original-src="//upload-images.jianshu.io/upload_images/12745724-48422ef751879020.png" data-original-width="960" data-original-height="1080" data-original-format="image/png" data-original-filesize="68468" data-image-index="1" style="cursor: zoom-in;" class="" src= "/img/loading.gif" data-lazy-src="//upload-images.jianshu.io/upload_images/12745724-48422ef751879020.png?imageMogr2/auto-orient/strip|imageView2/2/w/960/format/webp"></div></div><div class="image-caption">ReDoc</div></div><h2>五、OpenAPI</h2><p><strong>FastAPI</strong>使用用于定义API的OpenAPI标准为您的所有API生成“模式”。</p><h4>1. "模式"</h4><p>模式”是事物的定义或描述。 不是实现它的代码，只是抽象描述。</p><h4>2. API "模式"</h4><p>在这种情况下，OpenAPI是规定如何定义API模式的规范。</p><p>此OpenAPI架构将包括您的API路径，以及路径中包含的可能参数等。</p><h4>3. 数据 "模式"</h4><p>术语“模式”也可能表示某些数据的形状，例如JSON内容。</p><p>在这种情况下，这将意味着JSON属性及其具有的数据类型，等等。</p><h4>4. OpenAPI 和 JSON 模式</h4><ul><li><strong>OpenAPI</strong> ：为你的API定义API模式. 并且这个模式包含了API传输数据的定义和API接收数据的定义。</li><li><strong>JSON 模式</strong>, the standard for JSON data schemas.</li></ul><h4>5. 检查</h4><p>如果你对原生的OpenAPI是什么样子感兴趣，它只是一个自动生成的JSON，其中包含所有API的描述。</p><p>你可以直接转到: <a href="https://links.jianshu.com/go?to=http%3A%2F%2F127.0.0.1%3A8000%2Fopenapi.json" target="_blank">http://127.0.0.1:8000/openapi.json</a>.</p><p>它将会展示可能是这样开头的JSON：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-bash"><code class="  language-bash">&#123;    "openapi": "3.0.2",    "info": &#123;        "title": "Fast API",        "version": "0.1.0"    &#125;,    "paths": &#123;        "/items/": &#123;            "get": &#123;                "responses": &#123;                    "200": &#123;                        "description": "Successful Response",                        "content": &#123;                            "application/json": &#123;<p>…<br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><h4>6. 做什么的？</h4><p>此OpenAPI架构是为所包括的2个交互式文档系统提供支持的。</p><p>并且有数十种替代方案，全部基于OpenAPI。 您可以轻松地将这些替代方案中的任何一种添加到使用** FastAPI **构建的应用程序中。</p><p>您还可以使用它为与您的API通信的客户端自动生成代码。 例如，前端，移动或物联网应用程序。</p><h2>六、概括</h2><h3>Step 1: import <code>FastAPI</code></h3><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI app <span class="token operator">=</span> FastAPI<span class="token punctuation">(</span><span class="token punctuation">)</span><p>@app<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">“/“</span><span class="token punctuation">)</span><br><span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">root</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span><span class="token string">“message”</span><span class="token punctuation">:</span> <span class="token string">“Hello World”</span><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><p><code>FastAPI</code> 是为您的API提供所有功能的一个Python类。</p><blockquote><p><strong>技术细节</strong></p><ul><li>FastAPI是直接从Starlette继承的类。</li></ul><p>您也可以将所有Starlette功能与FastAPI一起使用.</p></blockquote><h3>Step 2: 创建一个 <code>FastAPI</code> 实例</h3><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-python"><code class="  language-python">app <span class="token operator">=</span> FastAPI<span class="token punctuation">(</span><span class="token punctuation">)</span> <p>@app<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">“/“</span><span class="token punctuation">)</span><br><span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">root</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span><span class="token string">“message”</span><span class="token punctuation">:</span> <span class="token string">“Hello World”</span><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><p>上面代码中<code>app</code> 变量就是<code>FastAPI</code>的一个实例.</p><p>这将是创建所有API的主要交互点。</p><p>该app与uvicorn在命令中引用的同一个app：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-css"><code class="  language-css">uvicorn <span class="token property">main</span><span class="token punctuation">:</span>app --reload<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>如果你创建的app像这样：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-python"><code class="  language-python">my_awesome_api <span class="token operator">=</span> FastAPI<span class="token punctuation">(</span><span class="token punctuation">)</span> <p>@my_awesome_api<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">“/“</span><span class="token punctuation">)</span><br><span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">root</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span><span class="token string">“message”</span><span class="token punctuation">:</span> <span class="token string">“Hello World”</span><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><p>将上段代码保存到 <code>main.py</code>, 然后你可以这样启动 <code>uvicorn</code> :</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-css"><code class="  language-css">uvicorn <span class="token property">main</span><span class="token punctuation">:</span>my_awesome_api --reload<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><h3>Step 3: 创建一个path 操作</h3><h4>Path</h4><p>这里的“路径”是指URL的最后一部分，从第一个<code>/</code>开始。</p><p>因此，在一个URL中：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-cpp"><code class="  language-cpp">https<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span>example<span class="token punctuation">.</span>com<span class="token operator">/</span>items<span class="token operator">/</span>foo<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>路径可能是:</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-undefined"><code class="  language-undefined">/items/foo<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><blockquote><p>“路径”通常也称为“端点”或“路由”。</p></blockquote><p>构建API时，“路径”是分离“关注点”和“资源”的主要方法。</p><h4>Operation</h4><p>"Operation" 这里指 HTTP 方法：</p><p>比如:</p><ul><li><code>POST</code></li><li><code>GET</code></li><li><code>PUT</code></li><li><code>DELETE</code></li></ul><p>...还有更少见的一些方法:</p><ul><li><code>OPTIONS</code></li><li><code>HEAD</code></li><li><code>PATCH</code></li><li><code>TRACE</code></li></ul><p>在HTTP协议中，你可以使用任意方法访问一个路径</p><hr><p>构建API时，通常使用这些特定的HTTP方法来执行特定的操作。</p><p>通常你会用到:</p><ul><li><code>POST</code>: 创建数据.</li><li><code>GET</code>: 读取数据.</li><li><code>PUT</code>: 更新数据.</li><li><code>DELETE</code>: 删除数据.</li></ul><p>因此，在OpenAPI中，每个HTTP方法都称为<code>方法</code>。</p><p>在以后的内容中，我们也把它称为方法。</p><h4>定义URL路由</h4><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-dart"><code class="  language-dart">from fastapi <span class="token keyword">import</span> FastAPI<p>app <span class="token operator">=</span> <span class="token function">FastAPI</span><span class="token punctuation">(</span><span class="token punctuation">)</span></p><p><span class="token metadata symbol">@app</span><span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">“/“</span><span class="token punctuation">)</span> <span class="token keyword">async</span> def <span class="token function">root</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span><span class="token string">“message”</span><span class="token punctuation">:</span> <span class="token string">“Hello World”</span><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><p><code>@app.get("/")</code>指明 <strong>FastAPI</strong> 下面的函数负责处理收到的请求：</p><ul><li>路径 <code>/</code></li><li>使用<code>get</code> 方法</li></ul><p>Python中 <code>@something</code> 语法被称为<code>装饰器</code>.</p><p>将这个装饰器放在函数的上方，就像一个漂亮的装饰帽(我猜想这也是这个属于名称的来源).</p><p>一个"装饰器"使用下方的函数，并对其进行处理.</p><p>在我们的例子中，这个装饰器告诉<strong>FastAPI</strong>，下方视图函数将会响应<strong>路径</strong><code>/</code>中的<strong>方法</strong><code>get</code>.</p><p>这就是<strong>路由操作装饰器</strong>.</p><p>你也可以其他方法的装饰器:</p><ul><li><code>@app.post()</code></li><li><code>@app.put()</code></li><li><code>@app.delete()</code></li></ul><p>还有一些比较少见的方法的装饰器:</p><ul><li><code>@app.options()</code></li><li><code>@app.head()</code></li><li><code>@app.patch()</code></li><li><code>@app.trace()</code></li></ul><h4>建议</h4><p>你可以使用任意的HTTP方法.</p><p><strong>FastAPI</strong>不强制任何特定函数。</p><p>此处提供的信息，仅供参考，并非必需。</p><p>例如，当使用 GraphQL , 你通常会只执行<code>post</code>方法</p><h3>Step 4: 定义<strong>路径操作函数</strong></h3><p>这是我们的 "<strong>路径操作函数</strong>":</p><ul><li><strong>路径</strong>:  <code>/</code>.</li><li><strong>操作</strong>:  <code>get</code>.</li><li><strong>函数</strong>: <code>@app.get("/")</code>下方的函数.</li></ul><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI<p>app <span class="token operator">=</span> FastAPI<span class="token punctuation">(</span><span class="token punctuation">)</span></p><p>@app<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">“/“</span><span class="token punctuation">)</span><br><span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">root</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span><span class="token string">“message”</span><span class="token punctuation">:</span> <span class="token string">“Hello World”</span><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><p>这是Python函数。</p><p>这个函数将会被 <strong>FastAPI</strong> 调用只要有 <code>GET</code>请求到URL "<code>/</code>".</p><p>在这个例子中，使用的是 <code>async</code> 函数。</p><hr><p>你也可以定义普通的函数而不是<code>async def</code>:</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI<p>app <span class="token operator">=</span> FastAPI<span class="token punctuation">(</span><span class="token punctuation">)</span></p><p>@app<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">“/“</span><span class="token punctuation">)</span><br><span class="token keyword">def</span> <span class="token function">root</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span><span class="token string">“message”</span><span class="token punctuation">:</span> <span class="token string">“Hello World”</span><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><h4>注释</h4><p>如果你不了解其中的区别，可以查看<em>"In a hurry?"</em> 章节关于 <a href="https://links.jianshu.com/go?to=https%3A%2F%2Ffastapi.tiangolo.com%2Fasync%2F%23in-a-hurry" target="_blank"><code>async</code> and <code>await</code> in the docs</a>.</p><h3>Step 5: 返回内容</h3><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">from</span> fastapi <span class="token keyword">import</span> FastAPI<p>app <span class="token operator">=</span> FastAPI<span class="token punctuation">(</span><span class="token punctuation">)</span></p><p>@app<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">“/“</span><span class="token punctuation">)</span><br><span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">root</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br> <span class="token keyword">return</span> <span class="token punctuation">&#123;</span><span class="token string">“message”</span><span class="token punctuation">:</span> <span class="token string">“Hello World”</span><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p><h4>可返回的类型</h4><blockquote><p>你可以返回一个<code>dict</code>, <code>list</code>，单独的值，比如<code>str</code>, <code>int</code>等</p><p>你也可以返回 <strong>Pydantic模型</strong>，在稍后的章节中会看到更多。</p></blockquote><p>在<strong>FastAPI</strong>中，许多其他的对象和模型都会被自动转换为JSON(包括ORM等)。</p><p>试着使用最适合您的方法，很有可能他们已经支持了。</p><h2>七、总结</h2><ul><li>Import <code>FastAPI</code>.</li><li>创建一个  <code>app</code> 实例.</li><li>编写一个 <strong>路径操作装饰器</strong> (比如<code>@app.get("/")</code>).</li><li>编写一个<strong>路径操作函数</strong> (比如上方的 <code>def root(): ...</code> ).</li><li>运行开发服务器(比如<code>uvicorn main:app --reload</code>).</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> FastAPI </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>FastAPI框架使用</title>
      <link href="python/fastapi-use/"/>
      <url>python/fastapi-use/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.cnblogs.com/neo98/p/12250730.html">https://www.cnblogs.com/neo98/p/12250730.html</a></p><div class="post">    <h1 class="postTitle"><pre><code>    &lt;a id=&quot;cb_post_title_url&quot; class=&quot;postTitle2&quot; href=&quot;https://www.cnblogs.com/neo98/p/12250730.html&quot;&gt;FastAPI框架快速构建高性能的api服务&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;postBody&quot;&gt;    &lt;div id=&quot;cnblogs_post_body&quot; class=&quot;blogpost-body &quot;&gt;        &lt;p&gt;&lt;a href=&quot;https://cloud.tencent.com/developer/article/1431448&quot;&gt;https://cloud.tencent.com/developer/article/1431448&lt;/a&gt;        &lt;/p&gt;        &lt;p&gt;&amp;nbsp;&lt;/p&gt;        &lt;p&gt;使用FastAPI可以非常快速的构建出一套高性能的api服务。下面通过实战演示一下：&lt;/p&gt;        &lt;blockquote&gt;            &lt;p&gt;fastapi目前仅支持python 3.6+以上版本。&lt;/p&gt;        &lt;/blockquote&gt;        &lt;h4 id=&quot;%E4%B8%80%E3%80%81%E5%AE%89%E8%A3%85fastapi%E5%92%8Cuvicorn&quot;&gt;&lt;strong&gt;一、安装fastapi和uvicorn&lt;/strong&gt;        &lt;/h4&gt;        &lt;pre class=&quot;prism-token token  language-javascript&quot;&gt;pip install fastapi</code></pre><p>pip install uvicorn</pre><br>            <h4 id="%E4%BA%8C%E3%80%81%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AAmain.py%E6%96%87%E4%BB%B6%EF%BC%8C%E7%BC%96%E5%86%99%E5%A6%82%E4%B8%8B%E4%BB%A3%E7%A0%81"><br>                <strong>二、新建一个main.py文件，编写如下代码</strong></h4><br>            <pre class="prism-token token  language-javascript"><span class="token keyword">from fastapi <span                    class="token keyword">import FastAPI</p><p>app <span class="token operator">= <span class="token function">FastAPI<span class="token punctuation">(<span                        class="token punctuation">)</p><p>@app<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span                            class="token string">“/“<span class="token punctuation">)<br>def <span class="token function">read_root<span class="token punctuation">(<span class="token punctuation">)<span                                class="token punctuation">:<br>    <span class="token keyword">return <span class="token punctuation">{<span class="token string">“Hello”<span            class="token punctuation">: <span class="token string">“World”<span class="token punctuation">}</p><p>@app<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span                class="token string">“/items/{item_id}”<span class="token punctuation">)<br>def <span class="token function">read_item<span class="token punctuation">(item_id<span                    class="token punctuation">: int<span class="token punctuation">, q<span class="token punctuation">: str <span                    class="token operator">= None<span class="token punctuation">)<span class="token punctuation">:<br>    <span class="token keyword">return <span class="token punctuation">{<span class="token string">“item_id”<span            class="token punctuation">: item_id<span class="token punctuation">, <span class="token string">“q”<span            class="token punctuation">: q<span            class="token punctuation">}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre><br>            <h4 id="%E4%B8%89%E3%80%81%E8%BF%90%E8%A1%8C%E6%8E%A5%E5%8F%A3%E6%9C%8D%E5%8A%A1"><strong>三、运行接口服务</strong><br>            </h4><br>            <p>在命令行，执行下面的命令</p><br>            <pre class="prism-token token  language-javascript">uvicorn main<span class="token punctuation">:app <span                    class="token operator">--reload</span></span></pre><br>            <h4 id="%E5%9B%9B%E3%80%81%E8%AF%B7%E6%B1%82%E6%8E%A5%E5%8F%A3"><strong>四、请求接口</strong></h4><br>            <p>运行成功后在浏览器打开<a href="http://127.0.0.1:8000/">http://127.0.0.1:8000</a> ,你将在一个JSON格式响应结果：</p><br>            <pre class="prism-token token  language-javascript"><span class="token punctuation">{<span                    class="token string">'hello'<span class="token punctuation">:<span class="token string">'world'<span                    class="token punctuation">}</span></span></span></span></span></pre><br>            <p>再次在浏览器打开<a href="http://127.0.0.1:8000/items/5?q=somequery%EF%BC%8C%E4%BD%A0%E5%B0%86%E5%9C%A8%E4%B8%80%E4%B8%AA%E5%A6%82%E4%B8%8BJSON%E6%A0%BC%E5%BC%8F%E5%93%8D%E5%BA%94%E7%BB%93%E6%9E%9C%EF%BC%9A">http://127.0.0.1:8000/items/5?q=somequery，你将在一个如下JSON格式响应结果：</a></p><br>            <pre class="prism-token token  language-javascript"><span class="token punctuation">{<span                    class="token string">'item_id'<span class="token punctuation">:<span class="token number">5<span                    class="token punctuation">,<span class="token string">'q'<span class="token punctuation">:<span                    class="token string">'somequery'<span class="token punctuation">}</span></span></span></span></span></span></span></span></span></pre><br>            <h4 id="%E4%BA%94%E3%80%81%E5%8F%AF%E8%A7%86%E5%8C%96API%E6%96%87%E6%A1%A3"><strong>五、可视化API文档</strong></h4><br>            <p>现在在浏览器中打开<a href="http://127.0.0.1:8000/docs,%E4%BD%A0%E4%BC%9A%E7%9C%8B%E5%88%B0%E4%B8%80%E4%B8%AA%E5%8F%AF%E4%BB%A5%E4%BA%A4%E4%BA%92%E7%9A%84api%E6%96%87%E6%A1%A3">http://127.0.0.1:8000/docs,你会看到一个可以交互的api文档</a></p><br>            <p>&nbsp;</p><br>            <p>&nbsp;</p><br>            <div><br>                <div><br>                    <p>你也可以其他方法的装饰器:</p><br>                    <ul><br>                        <li><code>@app.post()</code></li><br>                        <li><code>@app.put()</code></li><br>                        <li><code>@app.delete()</code></li><br>                    </ul><br>                    <p>还有一些比较少见的方法的装饰器:</p><br>                    <ul><br>                        <li><code>@app.options()</code></li><br>                        <li><code>@app.head()</code></li><br>                        <li><code>@app.patch()</code></li><br>                        <li><code>@app.trace(</code></li><br>                    </ul><br>                </div><br>                <br><br><br>                <h4>建议</h4><br>                <p>你可以使用任意的HTTP方法.</p><br>                <p>FastAPI不强制任何特定函数。</p><br>                <p>此处提供的信息，仅供参考，并非必需。</p><br>                <p>例如，当使用 GraphQL , 你通常会只执行<code>post</code>方法</p><br>                <p>&nbsp;</p><br>                <div><br>                    <div><br>                        <h4>总结</h4><br>                        <ul><br>                            <li>Import <code>FastAPI</code>.</li><br>                            <li>创建一个 <code>app</code> 实例.</li><br>                            <li>编写一个 <strong>路径操作装饰器</strong> (比如<code>@app.get("/")</code>).</li><br>                            <li>编写一个<strong>路径操作函数</strong> (比如上方的 <code>def root(): ...</code> ).</li><br>                            <li>运行开发服务器(比如<code>uvicorn main:app --reload</code>).</li></p><pre><code>                    &lt;/ul&gt;                &lt;/div&gt;            &lt;/div&gt;        &lt;/div&gt;        &lt;/div&gt;</code></pre></div>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> FastAPI </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Cmder简介</title>
      <link href="git/cmder-introduce/"/>
      <url>git/cmder-introduce/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://zhuanlan.zhihu.com/p/28400466">https://zhuanlan.zhihu.com/p/28400466</a></p><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在Windows系统上做开发，总是对其Terminal不满意。无论是CMD还是PowerShell，真是太丑了。现在安利大家一款神器，除了外观好看以外，功能也是强劲的狠。</p><p><img src= "/img/loading.gif" data-lazy-src="https://pic2.zhimg.com/v2-69ffd0f8964824475ce7b6b518cc3587_1200x500.gif"></p><p><img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/80/v2-da7f54e315dcb4f198d7b07ff6d23cd3_720w.jpg"></p><h2 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h2><ul><li>便携，解压即可用</li><li>自带git、ls、curl等命令</li><li>可设置命令别名</li><li>丰富的颜色主题（Solarized、Twilight、Ubuntu、xterm、Monokai，甚至接受自定）、可定制字体</li><li>支持tab分页、同屏多端口（支持水平分割、垂直分割）</li><li>支持自定terminal，无论是CMD、PowerShell、bash都可以，还可以注入环境变量</li></ul><p><img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/v2-69ffd0f8964824475ce7b6b518cc3587_b.jpg"><br><img src= "/img/loading.gif" data-lazy-src="https://pic1.zhimg.com/v2-450db5f7c6c245f53a5b06283b5a5fc0_b.jpg"></p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><ul><li>下载链接：<a href="https://link.zhihu.com/?target=http://cmder.net/">Cmder.net</a><br>分别有mini（6MB）和full（84MD）版本，都是portable的，解压即可使用。</li></ul><p>占用空间又小，所以直接放在u盘、云盘（像Onedrive、iCloud）里也行，达到多台设备同步设置的效果（我是把设置导出到gist上，更改就手动更新）。</p><ul><li>解压，双击Cmder.exe运行。</li></ul><h2 id="外观配置"><a href="#外观配置" class="headerlink" title="外观配置"></a>外观配置</h2><p>Font，右键Tab栏空白处，弹出菜单选择Settings，映入眼帘的就是字体设置了。建议使用字体Input Mono、Inconsolata、Consolas、Courier New。还可以加上中文字体，”Main font”设置下方的”Alternative font”添加CJK字体，在设置”Unicode ranges”成CJK的就好了。<br>Color Schemes，同样是在Settings中，左侧树形菜单中选择Features-&gt;Colors，就能来到Scheme设置界面。Cmder自带的Scheme很丰富，也可以通过自定Scheme，应用网络上简洁好看的风格。Github | joonro/ConEmu-Color-Themes提供了当前流行的Scheme安装方式。<br>Quake Style， 开启后，Cmder就变成了下拉式。按住” ctrl + <code>&quot;Cmder就从屏幕上方弹出，焦点转移就收回（可修改成再次按住&quot; ctrl +</code> “收回）。开启Quake Style之后极客感很强 !( •̀ ω •́ )!</p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> cmder </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Cmder使用</title>
      <link href="git/cmder-use/"/>
      <url>git/cmder-use/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.jianshu.com/p/552b7f0bb18c">https://www.jianshu.com/p/552b7f0bb18c</a></p><p>Cmder是Windows下非常好用的终端模拟器， 常用于替换windows自带的终端。它可以在不同的标签页中同时连接不同的底层Shell，包括cmd、PowerShell、Bash和WSL，并提供相关增强功能和更加便捷的操作方式，这也正是它被大家称作为Windows下的神器的原因。</p><div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 424px; background-color: transparent;"><div class="image-container-fill" style="padding-bottom: 43.0%;"></div><div class="image-view" data-width="986" data-height="424"><p><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-cbf8041249833a04.png" data-original-width="986" data-original-height="424" data-original-format="image/png" data-original-filesize="59056" data-image-index="0" style="cursor: zoom-in;" class="" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/7667789-cbf8041249833a04.png?imageMogr2/auto-orient/strip|imageView2/2/w/986/format/webp"></div></p></div><div class="image-caption">Cmder展示图片</div></div><p>正如Cmder官网所说，我们应该将Cmder看作一个软件包，而非单个软件，它包含了：</p><ul><li>控制台模拟器：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fconemu.github.io%2F" target="_blank">Conemu</a> （它是Cmder的基础）</li><li>Cmd.exe增强功能：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fmridgers.github.io%2Fclink%2F" target="_blank">clink</a>  （通过clink进一步增强cmd shell）</li><li>Unix tools on windows：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fgitforwindows.org%2F" target="_blank">git for windows</a></li></ul><blockquote><p>本文属于我的Cmder系列文章中的第一篇：《Cmder入门配置》</p></blockquote><h2>安装</h2><p><strong>安装方式一：</strong>在官网<a href="https://links.jianshu.com/go?to=http%3A%2F%2Fcmder.net%2F" target="_blank">Cmder</a>下载cmder压缩包，解压即可。这里<strong>注意</strong>解压路径不能位于需要管理员访问权限的地方，<strong>建议</strong>放在D盘并且确保路径中没有空格。</p><ul><li><p>将cmder添加到文件夹<strong>右键菜单</strong>（即添加Cmder here）：</p><p>以管理员权限打开 PowerShell；切换到 cmder 的解压路径；执行 <code>.\cmder.exe /REGISTER ALL</code>，即可添加，取消注册则执行 <code>.\cmder.exe /UNREGISTER ALL</code></p></li><li><p>为cmder创建桌面快捷方式。</p></li></ul><blockquote><p>如果你有自己的可执行程序，那么你可以考虑将他们放入 <code>%cmder_root%\bin</code> 目录，再将 <code>%cmder_root%\bin</code> 目录添加到 PATH 环境变量。</p><p>这里将上文的 <code>%cmder_root%</code> 修改为 <code>cmder.exe</code>所在路径，或者你可以考虑新建一个<code>%cmder_root%</code> 系统变量，或者将其也添加到PATH中（随意就好）。</p></blockquote><p><strong>安装方式二：</strong> 通过 scoop 安装（推荐）</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-shell"><code class="shell  language-shell"># 安装完整版（自带git-for-windows）scoop install cmder-full# 安装mini版，不带git，安装后如果想使用bash则还需做一些配置,可见我的系列文章scoop install cmder<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div><blockquote><p>scoop的安装和使用可参考我的相关文章：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fwww.thisfaner.com%2Fposts%2Fdevops%2Fwindows%2Fscoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7%2F" target="_blank">Scoop包管理工具 – 就是这个范儿</a></p></blockquote><h2>常用操作</h2><h3>中文配置</h3><p>进入seting界面：点击Cmder窗口左上角的图标 或者 右下角的 <code>三</code>图标，然后选择 <code>setting</code></p><p>设置中文界面： 选择<code>General-&gt;Interface language -&gt; zh:简体中文</code></p><div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 244px;"><div class="image-container-fill" style="padding-bottom: 31.979999999999997%;"></div><div class="image-view" data-width="763" data-height="244"><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-2dd1e8d59ee5908b.png" data-original-width="763" data-original-height="244" data-original-format="image/png" data-original-filesize="13776" data-image-index="1" style="cursor: zoom-in;" class="image-loading"></div></div><div class="image-caption">cmder01.png</div></div><h3>粘贴复制</h3><p>复制：只需选中一段文字那么该段文字就会被复制到剪贴板</p><p>粘贴：直接<code>鼠标右键</code>即可粘贴，或者使用 <code>Ctrl + v</code> 进行粘贴.</p><h3>设置为默认终端</h3><p>setting 👉 集成 👉 默认项目 👉 强制使用ConEmu作为控制台应用程序的默认终端`</p><p>如果允许某些程序出现错误，需要关闭此选项。</p><h3>cmd模式和bash模式</h3><p>新手可能会经常在cmd模式下输入bash相关的命令格式，导致相关错误；所以注意一下你当前在哪个模式。</p><p>比如在初次使用时，可能会出现切换不了路径的情况，这是因为你还没意识到自己在哪个模式下：</p><p>如果是用默认的<code>bash</code>, 可以直接 <code>cd /d/myworkstation</code> 这样跨盘切换。</p><p>如果用的是<code>cmd</code>模式, 需要先输入 <code>d:</code>来切换到d盘。</p><h3>配置cmder以下拉方式划出</h3><p>设置 👉 通用 👉 Quake 风格 👉</p><ul><li>勾选 Quake式向下滑动</li><li>勾选 失去焦点时自动隐藏</li><li>修改 动画时间 为 <code>150</code></li></ul><p>然后在 “通用” 设置处，设置 最小化和恢复 （Minimize/Restore hotkey ）时所使用的快捷键，默认为  <code>Ctrl + `</code></p><blockquote><p>如果你同时使用VS Code会发现 <code>Ctrl + `</code>快捷键在VS Code中是打开终端的默认快捷键；为避免冲突，我个人是选择将 cmder 的该快捷键修改为：  <code>Win + `</code></p></blockquote><h2>alias别名机制</h2><p><strong>Cmder增加了alias功能：</strong> 它让你用短短的指令执行一些常见但指令超长又难以记忆的语法；</p><p>在控制台输入<code>alias</code>可以查看现有别名。</p><p>并且它有分别应用于 cmd，bash和PowerShell的 别名 。</p><p><strong>1. cmd aliases：</strong></p><p>在<code>%CMDER_ROOT%\config\user-aliases.cmd</code>中添加 cmd aliases，它<strong>仅用于 cmd 命令</strong></p><p>示例：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-cmd"><code class="cmd  language-cmd">ls=ls --show-control-chars -F --color $*pwd=cdclear=cls<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div><blockquote><p>具体配置可参考：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fcmderdev%2Fcmder%2Fblob%2Fmaster%2FREADME.md%23cmdercmdexe-aliases" target="_blank">cmder/README.md </a></p></blockquote><p><strong>2. Bash/Mintty aliases：</strong></p><p>对于bash，其配置文件的加载顺序是：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-bash"><code class="  language-bash">$CMDER_ROOT/config/profile.d/*.sh$CMDER_ROOT/config/user-profile.sh$HOME/.bashrc<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div><p>所以我们可以在上面的文件中添加 alias 即可。</p><p>几个示例：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-shell"><code class="shell  language-shell">alias l.='ls -d .* --color=tty'alias ll='ls -l --color=tty'alias ls='ls --color=tty'<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div><p>由于 Git for Windows 会自动创建 <code>~/.bash_profile</code>，而对此cmder会提示有冲突，此时可以创建一个<code>~/.profile</code>并在该文件中添加别名。（这里 <code>~</code>表示<code>$HOME</code>）</p><p><strong>3.PowerShell aliases：</strong></p><p>直接使用PowerShell 的 <code>alias</code>命令添加或在下面的文件中添加：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-dart"><code class="  language-dart"><span class="token string">'$ENV:CMDER_ROOT\config\profile.d\*.ps1'</span><span class="token string">'$ENV:CMDER_ROOT\config\user-profile.ps1'</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div><p>这里<code>$ENV:CMDER_ROOT</code> 指 cmder 的安装目录。</p><h2>Cmder启动选项</h2><div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 303px;"><div class="image-container-fill" style="padding-bottom: 39.82%;"></div><div class="image-view" data-width="761" data-height="303"><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-b643de5f075b918d.png" data-original-width="761" data-original-height="303" data-original-format="image/png" data-original-filesize="13314" data-image-index="2" style="cursor: zoom-in;" class="image-loading"></div></div><div class="image-caption">cmder02.png</div></div><p>相关介绍</p><ul><li><p>在 启动（Startup）处设置 cmder 启动时需要执行的任务</p><p>默认选择的启动项是 <code>&#123;cmd::Cmder&#125;</code> 这个命名任务，我们可以更改成其它的命令任务或者直接切换到其它的启动项。</p><p>当选中某个命名任务时，下面的  "选中的任务内容" 下会显示该任务执行的具体内容</p></li><li><p>我们也可以在 <code>启动 -&gt; 任务</code>（<code>startup -&gt; tasks</code>）处更改和添加命名任务。</p></li></ul><blockquote><p>这里<code>cmd::Cmder</code>前面的cmd标明它是cmd模式，我们可以看到还有 bash 和 PowerShell等模式</p></blockquote><h3>自定义启动目录</h3><p>下面就来克隆现有的<code>&#123;cmd::Cmder&#125;</code>添加一个设置自定义的启动目录的任务(Task)：</p><div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 510px;"><div class="image-container-fill" style="padding-bottom: 66.84%;"></div><div class="image-view" data-width="763" data-height="510"><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-dea640daf3733022.png" data-original-width="763" data-original-height="510" data-original-format="image/png" data-original-filesize="56937" data-image-index="3" style="cursor: zoom-in;" class="image-loading"></div></div><div class="image-caption">cmder03.png</div></div><p>设置启动目录</p><div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 508px;"><div class="image-container-fill" style="padding-bottom: 66.75%;"></div><div class="image-view" data-width="761" data-height="508"><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-ba0fcc97010f0e25.png" data-original-width="761" data-original-height="508" data-original-format="image/png" data-original-filesize="35096" data-image-index="4" style="cursor: zoom-in;" class="image-loading"></div></div><div class="image-caption">cmder04.png</div></div><ul><li>任务参数：下面来看 “Task parameters”命令参数，阅读实例可知参数 <code>/icon</code>指定<strong>图标</strong>位置，<code>/dir</code> 指定启动目录，所以我们可以添加下面的参数：<code>/icon "%CMDER_ROOT%\icons\cmder.ico" /dir "C:\Users\Fan"</code></li><li>记得在 <code>startup</code> 的“ Specified named task” 处选择 <code>cmd::diy1</code></li><li>保存设置，退出，重新打开 cmder 查看效果</li></ul><h3>为任务添加快捷键</h3><p>在上图中我们可以发现还可以为每个任务设置 <code>热键</code> ，下面是我个人的热键设置：</p><ul><li>打开一个 cmd 任务标签页：<code>Alt+c</code></li><li>打开一个PowerShell 任务标签页：<code>Alt+p</code></li><li>打开一个 bash 任务标签页：<code>Alt+b</code></li><li>打开一个 WSL 任务标签页：<code>Alt+l</code></li></ul><h2>Cmder连接Linux子系统（WSL）</h2><p>Windows Subsystem for Linux（简称WSL）。</p><p>ConEmu（包括基于 ConEmu 修改的 cmder） 等终端模拟器也已经适配了 WSL 环境。</p><p>连接方式：</p><ul><li>添加一个标签页时（点击右下角的 ➕），选择 <code>WSL --&gt; bash</code></li><li>或直接将启动任务指定为 <code>&#123;WSL::bash&#125;</code></li></ul><p>Windows系统的分区全部挂载于Linux子系统的 <code>/mnt</code> 目录</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-shell"><code class="shell  language-shell">$ ls /mntc  d  e  f  g<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div><p>这表示可用<code>/mnt/c</code> 来访问 C: 盘；这里还可以进行一些调整（例如创建从<code>/c</code>到的符号链接<code>/mnt/c</code>）</p><p>也可以在<strong>Linux子系统中</strong>设置如下别名以便于切换：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-bash"><code class="bash  language-bash"># ~/.bashrc alias cdc='cd /mnt/c/'alias cdd='cd /mnt/d/'alias cde='cd /mnt/e/'<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div><h2>其它问题</h2><h3>中文乱码</h3><p>在 <code>Startup -&gt; Environment</code> 中添加下面的语句：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-bash"><code class="  language-bash">set LANG=zh_CN.UTF-8<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><blockquote><p>如果没有出现乱码，则可以不添加。</p><p>如果打开的文本文件的编码方式不是 utf-8 那么在cmder中查看时会乱码，这种情况需要转换该文件的编码方式为 utf-8</p></blockquote><div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 243px;"><div class="image-container-fill" style="padding-bottom: 31.929999999999996%;"></div><div class="image-view" data-width="761" data-height="243"><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-a3c4e6f00d7bdd85.png" data-original-width="761" data-original-height="243" data-original-format="image/png" data-original-filesize="27962" data-image-index="5" style="cursor: zoom-in;" class="image-loading"></div></div><div class="image-caption">cmder05.png</div></div><h3>查看git log时乱码</h3><p>这一般是git的配置问题，执行下面的命令，来配置git log的输出</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-csharp"><code class="  language-csharp">git config <span class="token operator">--</span><span class="token keyword">global</span> i18n<span class="token punctuation">.</span>logoutputencoding utf<span class="token operator">-</span><span class="token number">8</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><blockquote><p>或者在 .gitconfig 文件中配置</p><p>更多git乱码问题见： <a href="https://links.jianshu.com/go?to=https%3A%2F%2Fblog.csdn.net%2Fguiying123456%2Farticle%2Fdetails%2F62881400" target="_blank">cmder中文乱码 </a></p></blockquote><h3>ssh agent</h3><p>每次想要向远程git仓库推送更新时，都需要先启动ssh代理，再加载(使用ssh-add)私钥，否则就报错而感到很烦。那么可以参考下面的解决方法：</p><p><strong>cmd 模式中：</strong></p><p>官方文档中有说在 cmd 模式中如何处理 ssh agent的相关问题：</p><p>To start the vendored SSH agent simply call <code>start-ssh-agent</code>, which is in the <code>vendor/git-for-windows/cmd</code> folder.</p><p>If you want to run SSH agent on startup, include the line <code>@call "%GIT_INSTALL_ROOT%/cmd/start-ssh-agent.cmd"</code> in <code>%CMDER_ROOT%/config/user-profile.cmd</code> (usually just uncomment it).</p><p><strong>bash模式中：</strong></p><p>官方文档中没有说如何在bash模式中处理ssh-agent的问题，但我们可以这样解决。</p><p>在<code>$HOME/.bashrc</code>或<code>$HOME/.profilec</code>文件中添加如下内容：</p><div class="_2Uzcx_"><button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button><pre class="line-numbers  language-shell"><code class="shell  language-shell"># 启动一个 ssh-agent 进程 eval "$(ssh-agent -s)"# 这里同时添加了两个私钥ssh-add "C:/Users/Fan/.ssh/one_rsa" "C:/Users/Fan/.ssh/two_id_rsa"# 清除上面命令的输出内容clear<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div><blockquote><p>更多 ssh-agent 介绍可参考: <a href="https://www.jianshu.com/p/8e88d4b11dec" target="_blank">SSH相关命令 </a>中的ssh-agent部分</p><p>或者查看：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fdev.to%2Fqm3ster%2Fsetting-up-gitsshgpg-on-windows-5c85" target="_blank">Setting up git+ssh+gpg on Windows</a></p></blockquote><h2>补充</h2><p>点击右下角的锁（🔒 :lock: ）即可锁定视窗 ，可以让窗口无法再输入内容。</p><h3>正确退出</h3><p>我们一直是习惯于直接点击右上角的 × 来关闭程序，但是正确的退出方法应该是在cmder中输入 <code>exit</code> 来进行退出，只有这样退出历史记录才会保留，你在下次打开cmder时才可向上翻看上次历史。</p><h3>Cmder系列文章</h3><p>下面是我的系列文章</p><ul><li><a href="https://links.jianshu.com/go?to=https%3A%2F%2Fwww.thisfaner.com%2Fposts%2Ftools%2Fcmder%2F" target="_blank">Cmder入门配置 – 就是这个范儿</a></li><li><a href="https://links.jianshu.com/go?to=https%3A%2F%2Fwww.thisfaner.com%2Fposts%2Ftools%2Fcmder%25E8%25BF%259B%25E9%2598%25B6%25E9%2585%258D%25E7%25BD%25AE%2F" target="_blank">Cmder进阶配置 – 就是这个范儿</a></li><li><a href="https://links.jianshu.com/go?to=https%3A%2F%2Fwww.thisfaner.com%2Fposts%2Ftools%2F%25E6%25B7%25B1%25E5%25BA%25A6%25E5%25AE%259A%25E5%2588%25B6cmder%2F" target="_blank">深度定制Cmder – 就是这个范儿</a></li><li><a href="https://links.jianshu.com/go?to=https%3A%2F%2Fwww.thisfaner.com%2Fposts%2Fdevops%2Fwindows%2Fpowershell%25E4%25B8%25BB%25E9%25A2%2598%25E8%25AE%25BE%25E7%25BD%25AE%2F" target="_blank">PowerShell主题设置 – 就是这个范儿</a></li><li><a href="https://links.jianshu.com/go?to=https%3A%2F%2Fwww.thisfaner.com%2Fposts%2Ftools%2Fpowerlevel9kzsh%25E4%25B8%258B%25E6%259C%2580%25E6%25A3%2592%25E7%259A%2584powerline%25E4%25B8%25BB%25E9%25A2%2598%2F" target="_blank">Powerlevel9k：zsh下最棒的Powerline主题 – 就是这个范儿</a></li></ul><p>如果想要将Cmder对应的任务标签页配置为如下效果，则可参考该系列文章：</p><ul><li><p></p><p></p>在Cmd下的效果：<div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 424px;"><div class="image-container-fill" style="padding-bottom: 43.0%;"></div><div class="image-view" data-width="986" data-height="424"><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-1a6ed28bd6b97073.png" data-original-width="986" data-original-height="424" data-original-format="image/png" data-original-filesize="30427" data-image-index="6" style="cursor: zoom-in;" class="image-loading"></div></div><div class="image-caption">cmder-cmd-20191215162952.png</div></div></li><li><p></p><p></p>PowerShell下不同主题的效果：<div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 328px;"><div class="image-container-fill" style="padding-bottom: 44.81%;"></div><div class="image-view" data-width="732" data-height="328"><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-1c39094b99509f9c.png" data-original-width="732" data-original-height="328" data-original-format="image/png" data-original-filesize="53308" data-image-index="7" style="cursor: zoom-in;" class="image-loading"></div></div><div class="image-caption">powershell-theme01.png</div></div></li><li><p></p><p></p>WSL bash下的效果：<div class="image-package"><div class="image-container" style="max-width: 700px; max-height: 424px;"><div class="image-container-fill" style="padding-bottom: 43.0%;"></div><div class="image-view" data-width="986" data-height="424"><img data-original-src="https://upload-images.jianshu.io/upload_images/7667789-0d3b2d8b9dbeecdf.png" data-original-width="986" data-original-height="424" data-original-format="image/png" data-original-filesize="59056" data-image-index="8" style="cursor: zoom-in;" class="image-loading"></div></div><div class="image-caption">cmder-zsh-p9k-20191215153654.png</div></div></li></ul><h3>参考</h3><p>官方文档：</p><ul><li>Readme：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fcmderdev%2Fcmder%2Fblob%2Fmaster%2FREADME.md" target="_blank">cmder/README.md at master · cmderdev/cmder</a></li><li>wiki：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fcmderdev%2Fcmder%2Fwiki" target="_blank">Home · cmderdev/cmder Wiki</a></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> cmder </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>GitBook简介</title>
      <link href="git/gitbook-introduce/"/>
      <url>git/gitbook-introduce/</url>
      
        <content type="html"><![CDATA[<p>原文链接： <a href="https://www.jianshu.com/p/421cc442f06c">https://www.jianshu.com/p/421cc442f06c</a></p><h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><p>GitBook 是一个基于 Node.js 的命令行工具，可使用 Github/Git 和 Markdown 来制作精美的电子书，GitBook 并非关于 Git 的教程。</p><h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>由于之前都把零散的知识都写在 Gist 上，要查找的时候不是很系统化，所以打算挪到 GitBook 上来统一管理，而且 GitBook 写完编译后可以生成静态页面发布到博客上，逼格满满的样子。</p><h2 id="GitBook-准备工作"><a href="#GitBook-准备工作" class="headerlink" title="GitBook 准备工作"></a>GitBook 准备工作</h2><h3 id="安装-Node-js"><a href="#安装-Node-js" class="headerlink" title="安装 Node.js"></a>安装 Node.js</h3><p>GitBook 是一个基于 Node.js 的命令行工具，下载安装 Node.js，安装完成之后，你可以使用下面的命令来检验是否安装成功。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ node -v</span><br><span class="line">v7.7.1</span><br></pre></td></tr></table></figure><h3 id="安装-GitBook"><a href="#安装-GitBook" class="headerlink" title="安装 GitBook"></a>安装 GitBook</h3><p>输入下面的命令来安装 GitBook。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm install gitbook-cli -g</span><br></pre></td></tr></table></figure><p>安装完成之后，你可以使用下面的命令来检验是否安装成功。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ gitbook -V</span><br><span class="line">CLI version: 2.3.2</span><br><span class="line">GitBook version: 3.2.3</span><br></pre></td></tr></table></figure><p>更多详情请参照 <a href="https://links.jianshu.com/go?to=https://github.com/GitbookIO/gitbook/blob/master/docs/setup.md">GitBook 安装文档</a> 来安装 GitBook。</p><h3 id="编辑器"><a href="#编辑器" class="headerlink" title="编辑器"></a>编辑器</h3><p>可以用 VsCode、Typora 等自己喜欢的来编辑。</p><h2 id="先睹为快"><a href="#先睹为快" class="headerlink" title="先睹为快"></a>先睹为快</h2><p>GitBook 准备工作做好之后，我们进入一个你要写书的目录，输入如下命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ gitbook init</span><br><span class="line">warn: no summary file in this book</span><br><span class="line">info: create README.md</span><br><span class="line">info: create SUMMARY.md</span><br><span class="line">info: initialization is finished</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>GitBook 从懵逼到入门</title>
      <link href="git/gitbook-introduce2/"/>
      <url>git/gitbook-introduce2/</url>
      
        <content type="html"><![CDATA[<h2 id="转载声明"><a href="#转载声明" class="headerlink" title="转载声明"></a>转载声明</h2><p>原文链接： <a href="https://blog.csdn.net/lu_embedded/article/details/81100704">https://blog.csdn.net/lu_embedded/article/details/81100704</a></p><p>本文从 “是什么”、“为什么”、“怎么办”、“好不好” 四个维度来介绍 GitBook，带你从黑暗之中走出来，get 这种美妙的写作方式。</p><h2 id="是什么？"><a href="#是什么？" class="headerlink" title="是什么？"></a>是什么？</h2><p>在我认识 GitBook 之前，我已经在使用 Git 了，毋容置疑，Git 是目前世界上最先进的分布式版本控制系统。</p><p>我认为 Git 不仅是程序员管理代码的工具，它的分布式协作方式同样适用于很多场合，其中一个就是写作（这会是一个引起社会变革的伟大的工具！）。所以在我发现 GitBook 之前，实际上我已经无数次想象过它的使用场景了。</p><p>咋一看 GitBook 的名字，你可能会认为它是关于 Git 的一本书。而当你有所了解之后，你也许会认为它是一个使用 Git 构建电子书的工具。其实不然，GitBook 与 Git 的关系，就像雷锋塔和雷锋那样，没有一点关系！</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180718161255281?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1Y2t5ZGFyY3k=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70#pic_center"></p><p>实际上，GitBook 是一个基于 Node.js 的命令行工具，支持 Markdown 和 AsciiDoc 两种语法格式，可以输出 HTML、PDF、eBook 等格式的电子书。所以我更喜欢把 GitBook 定义为文档格式转换工具。<br>　　<br>所以，GitBook 不是 Markdown 编辑工具，也不是 Git 版本管理工具。市面上我们可以找到很多 Markdown 编辑器，比如 Typora、MacDown、Bear、MarkdownPad、MarkdownX、JetBrains’s IDE（需要安装插件）、Atom、简书、CSDN 以及 GitBook 自家的 GitBook Editor 等等。</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180718161741325?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1Y2t5ZGFyY3k=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70#pic_center"></p><p>但 GitBook 又与 Markdown 和 Git 息息相关，因为只有将它们结合起来使用，才能将它们的威力发挥到极致！因此，通常我们会选择合适的 Markdown 编辑工具以获得飞一般的写作体验；使用 GitBook 管理文档，预览、制作电子书；同时通过 Git 管理书籍内容的变更，并将其托管到云端（比如 GitHub、GitLab、码云，或者是自己搭建的 Git 服务器），实现多人协作。</p><p>实际上，GitBook Editor 对于新手来说是个不错的选择，它集成了 GitBook、Git、Markdown 等功能，还支持将书籍同步到 gitbook.com 网站，使我们可以很方便地编辑和管理书籍。但是不幸的是，GitBook Editor 的注册和登录需要翻墙，即便注册成功了也可能登录不上，似乎是因为网站最近在升级。</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180718171731114?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1Y2t5ZGFyY3k=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70#pic_center"></p><p>因此，我推荐，也是我目前使用的搭配是 GitBook + Typora + Git。</p><h2 id="为什么？"><a href="#为什么？" class="headerlink" title="为什么？"></a>为什么？</h2><p>通常，我们最开始学习和使用的办公软件就是 Word、Excel 和 PowerPoint。这里不是说它们已经过时了，不是说 GitBook 能够替代它们。</p><p>相反，Microsoft 的办公软件很优秀并且经受了时间的考验，但是正因为它功能丰富，导致稍显臃肿（二八定律：80%的时间里我们只会只用20%的功能），同时因为它存在以二进制格式保存、软件不兼容、格式不兼容、难以进行版本控制、难以实时分享预览、难以多人协作等短板。而这恰恰是 GitBook + Markdown + Git 的长处。</p><h2 id="简单来说，GitBook-Markdown-Git-带来的好处有："><a href="#简单来说，GitBook-Markdown-Git-带来的好处有：" class="headerlink" title="简单来说，GitBook + Markdown + Git 带来的好处有："></a>简单来说，GitBook + Markdown + Git 带来的好处有：</h2><ul><li>语法简单</li><li>兼容性强</li><li>导出方便</li><li>专注内容</li><li>团队协作</li></ul><p>所以，如果你和我一样，不满足于传统的写作方式，正在寻找一种令人愉悦的写作方式，那么该尝试使用 GitBook 啦！</p><p>当然，GitBook 不是万能的，当我们需要复杂排版时，依然需要依托于 Word 等工具。但不用担心，因为我们可以把 Markdown 格式的文档导出为 Word 格式，再进一步加工。</p><h2 id="怎么办？"><a href="#怎么办？" class="headerlink" title="怎么办？"></a>怎么办？</h2><p>怎么安装<br>当你听了我的怂恿，并决定尝试使用 GitBook 的时候，首先面临的问题是 —— 如何搭建 GitBook 环境？</p><p>因为 GitBook 是基于 Node.js，所以我们首先需要安装 Node.js（下载地址：<a href="https://nodejs.org/en/download/%EF%BC%89%EF%BC%8C%E6%89%BE%E5%88%B0%E5%AF%B9%E5%BA%94%E5%B9%B3%E5%8F%B0%E7%9A%84%E7%89%88%E6%9C%AC%E5%AE%89%E8%A3%85%E5%8D%B3%E5%8F%AF%E3%80%82">https://nodejs.org/en/download/），找到对应平台的版本安装即可。</a></p><p>现在安装 Node.js 都会默认安装 npm（node 包管理工具），所以我们不用单独安装 npm，打开命令行，执行以下命令安装 GitBook：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g gitbook-cli</span><br></pre></td></tr></table></figure><p>安装完之后，就会多了一个 gitbook 命令（如果没有，请确认上面的命令是否加了 -g）。</p><p>上面我推荐的是 GitBook + Typora + Git，所以你还需要安装 Typora（一个很棒的支持 macOS、Windows、Linux 的 Markdown 编辑工具）和 Git 版本管理工具。戳下面：</p><ul><li>Typora 下载地址：<code>https://typora.io/</code></li><li>Git 下载地址：<code>https://git-scm.com/downloads</code></li></ul><h2 id="怎么使用"><a href="#怎么使用" class="headerlink" title="怎么使用"></a>怎么使用</h2><p>想象一下，现在你准备构建一本书籍，你在硬盘上新建了一个叫 mybook 的文件夹，按照以前的做法，你会新建一个 Word 文档，写上标题，然后开始巴滋巴滋地笔耕。但是现在有了 GitBook，你首先要做的是在 mybook 文件夹下执行以下命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitbook init</span><br></pre></td></tr></table></figure><p>执行完后，你会看到多了两个文件 —— README.md 和 SUMMARY.md，它们的作用如下：</p><ul><li>README.md —— 书籍的介绍写在这个文件里</li><li>SUMMARY.md —— 书籍的目录结构在这里配置</li></ul><p>这时候，我们启动恭候多时的 Typora 来编辑这两个文件了：</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/2018071818281621?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1Y2t5ZGFyY3k=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70#pic_center"></p><p>编辑 SUMMARY.md 文件，内容修改为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"># 目录</span><br><span class="line"></span><br><span class="line">* [前言](README.md)</span><br><span class="line">* [第一章](Chapter1&#x2F;README.md)</span><br><span class="line">  * [第1节：衣](Chapter1&#x2F;衣.md)</span><br><span class="line">  * [第2节：食](Chapter1&#x2F;食.md)</span><br><span class="line">  * [第3节：住](Chapter1&#x2F;住.md)</span><br><span class="line">  * [第4节：行](Chapter1&#x2F;行.md)</span><br><span class="line">* [第二章](Chapter2&#x2F;README.md)</span><br><span class="line">* [第三章](Chapter3&#x2F;README.md)</span><br><span class="line">* [第四章](Chapter4&#x2F;README.md)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>然后我们回到命令行，在 mybook 文件夹中再次执行 gitbook init 命令。GitBook 会查找 SUMMARY.md 文件中描述的目录和文件，如果没有则会将其创建。</p><p>Typora 是所见即所得（实时渲染）的 Markdown 编辑器，这时候它是这样的：</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180718185415241?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1Y2t5ZGFyY3k=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70#pic_center"></p><p>接着我们执行 gitbook serve 来预览这本书籍，执行命令后会对 Markdown 格式的文档进行转换，默认转换为 html 格式，最后提示 “Serving book on <a href="http://localhost:4000”。嗯，打开浏览器看一下吧：">http://localhost:4000”。嗯，打开浏览器看一下吧：</a></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180718185251753?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1Y2t5ZGFyY3k=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70#pic_center"></p><p>当你写得差不多，你可以执行 gitbook build 命令构建书籍，默认将生成的静态网站输出到 _book 目录。实际上，这一步也包含在 gitbook serve 里面，因为它们是 HTML，所以 GitBook 通过 Node.js 给你提供服务了。</p><p>当然，build 命令可以指定路径：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitbook build [书籍路径] [输出路径]</span><br></pre></td></tr></table></figure><p>serve 命令也可以指定端口：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitbook serve --port 2333</span><br></pre></td></tr></table></figure><p>你还可以生成 PDF 格式的电子书：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitbook pdf .&#x2F; .&#x2F;mybook.pdf</span><br></pre></td></tr></table></figure><p>生成 epub 格式的电子书：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitbook epub .&#x2F; .&#x2F;mybook.epub</span><br></pre></td></tr></table></figure><p>生成 mobi 格式的电子书：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitbook mobi .&#x2F; .&#x2F;mybook.mobi</span><br></pre></td></tr></table></figure><p>如果生成不了，你可能还需要安装一些工具，比如 ebook-convert。或者在 Typora 中安装 Pandoc 进行导出。</p><p>除此之外，别忘了还可以用 Git 做版本管理呀！在 mybook 目录下执行 git init 初始化仓库，执行 git remote add 添加远程仓库（你得先在远端建好）。接着就可以愉快地 commit，push，pull … 啦！</p><p>不是程序员的小伙伴可能不太喜欢用命令行，那其实版本管理这部分可以下载安装 Git 或 GitHub 这些客户端程序，在图形界面上操作也是可以完成工作的。</p><p>好不好？<br>额… 你觉得好不好嘛？</p><p>反正我觉得挺好的，特别是对我这种懒得排版，又想随时随地写作的宝宝来说。而且能够查看每个版本内容变更的情况，同时又避免了硬盘单一故障带来的风险。</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190509150744837.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1Y2t5ZGFyY3k=,size_16,color_FFFFFF,t_70#pic_center"></p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Scoop简识</title>
      <link href="git/scoop-introduce/"/>
      <url>git/scoop-introduce/</url>
      
        <content type="html"><![CDATA[<p>本文转载自:<a href="https://www.thisfaner.com/posts/devops/windows/scoop%E5%8C%85%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7/#scoop%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4">Scoop包管理工具</a></p><h2 id="scoop-包管理工具介绍">Scoop 包管理工具介绍<span class="anchor hide" data-clipboard-text="https://www.thisfaner.com/posts/devops/windows/scoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7/#scoop-包管理工具介绍" aria-label="null" style="position: relative;"><span style="font-size: 1rem; position: absolute; top: 50%; transform: translateY(-50%); right: -2rem;">🔗</span></span></h2><p>Windows下常用的包管理工具有：</p><ul><li>Scoop</li><li>Chocolatey</li></ul><p>由于Scoop更容易配置（相比于Chocolatey），这里选择 Scoop</p><p>使用Scoop安装最佳的应用程序通常称为“便携式”应用程序：即在解压缩时独立运行的压缩程序文件，不存在更改注册表或将文件放在程序目录之外的副作用。</p><p>对于像 VirtualBox、Docker for Windows 这些需要高权限的软件还是会用安装包在用户界面下自定义安装。</p><p><strong>对比Scoop和Chocolatey：</strong></p><p>Chocolatey 能更加全面地包办绝大多数的软件安装，适应重度需求；而 Scoop 则更加简单利落，容易自定义软件包，适应中低需求。</p><p>Chocolatey 的安装脚本默认要求管理员权限安装，同时非管理员安装默认路径是&nbsp;<code>C:\ProgramData\chocoportable</code>，这对于非高权限用户来说不太友好（比如没有管理员权限的工作机安装会比较折腾），而 Scoop 默认仅需普通用户权限，安装路径是&nbsp;<code>%USERPROFILE%\scoop</code>&nbsp;则显得比较清新，不过这都是<strong>可以根据需求修改</strong>的了。</p><p>Scoop更专注于开源的命令行开发人员工具 。</p><p>Github页面： <a href="https://github.com/lukesampson/scoop" title="lukesampson/scoop: A command-line installer for Windows.">scoop: A command-line installer for Windows.</a></p><h2 id="scoop安装配置">Scoop安装配置<span class="anchor hide" data-clipboard-text="https://www.thisfaner.com/posts/devops/windows/scoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7/#scoop安装配置" style="position: relative;"><span style="font-size: 1rem; position: absolute; top: 50%; transform: translateY(-50%); right: -2rem;">🔗</span></span></h2><p>默认设置已配置为用户级别<strong>安装的程序</strong>和Scoop本身都位于 <code>C:\Users\&lt;user&gt;\scoop </code></p><p>全局安装的程序（所有用户可用）（<code>--global</code>）位于<code>C\ProgramData\scoop</code>中。可以通过环境变量更改这些设置 。</p><p>所以安装时先通过配置环境变量来配置其安装路径；然后在PowerShell运行命令下载。</p><p><strong>Install Scoop to a Custom Directory</strong></p><div data-lang="Code" class="language-code"><pre><code>[environment]::setEnvironmentVariable('SCOOP','D:\Scoop','User')$env:SCOOP='D:\Scoop'iex (new-object net.webclient).downloadstring('https://get.scoop.sh')</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><blockquote><p>相当于在用户变量中设置  <code>SCOOP=D:\Scoop</code></p><p>具体安装方法见其Github</p></blockquote><p><strong>Configure Scoop to install global programs to a Custom Directory</strong>（可选，建议不改）</p><div data-lang="Code" class="language-code"><pre><code>[environment]::setEnvironmentVariable('SCOOP_GLOBAL','D:\Scoop\GlobalScoopApps','Machine')$env:SCOOP_GLOBAL='D:\Scoop\GlobalScoopApps'</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><blockquote><p>相当于在系统变量中设置： <code>SCOOP_GLOBAL=D:\Scoop\GlobalScoopApps</code>；默认是在  <code>C:\ProgramData\scoop</code>，感觉不应该更改。</p></blockquote><p>为什么需要全局安装呢？我想应该 对于那些 要求管理员权限的程序需要安装在全局</p><p><a href="https://github.com/lukesampson/scoop/wiki/Global-Installs">Global Installs / scoop Wiki</a> ，像字体等需要给所有用户使用，所以需要使用全局安装。</p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-powershell" data-lang="powershell"><span class="c"># 初次安装也可选择安装下面这些，其中sudo要先进行本地安装</span><span class="n">scoop</span> <span class="n">install</span> <span class="n">sudo</span><span class="c"># 下面是全局安装的示例：个人感觉这几个软件还是直接进行本地安装更好</span><span class="n">sudo</span> <span class="n">scoop</span> <span class="n">install</span> <span class="n">7zip</span> <span class="n">git</span> <span class="n">openssh</span> <span class="p">-</span><span class="n">-global</span><span class="c"># 更新同样需要sudo 和 -g</span><span class="n">sudo</span> <span class="n">scoop</span> <span class="n">update</span> <span class="n">7zip</span> <span class="n">-g</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><p><strong>Multi-connection downloads with aria2</strong></p><p>scoop可通过aria2来进行多任务下载：</p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">scoop install aria2</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><h2 id="scoop常用命令">Scoop常用命令<span class="anchor hide" data-clipboard-text="https://www.thisfaner.com/posts/devops/windows/scoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7/#scoop常用命令" style="position: relative;"><span style="font-size: 1rem; position: absolute; top: 50%; transform: translateY(-50%); right: -2rem;">🔗</span></span></h2><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span><span class="lnt">11</span><span class="lnt">12</span><span class="lnt">13</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">scoop <span class="nb">help</span> <span class="c1">#查看帮助</span>scoop <span class="nb">help</span> &lt;某个命令&gt; <span class="c1"># 具体查看某个命令的帮助</span>scoop install <span class="c1">#安装 APP</span>scoop uninstall <span class="c1">#卸载 APP</span>scoop list <span class="c1">#列出已安装的 APP</span>scoop search <span class="c1">#搜索 APP</span>scoop update <span class="c1">#更新 Scoop 自身</span>scoop update appName1 appName2 <span class="c1"># 更新某些app</span>scoop update *  <span class="c1"># 更新所有 app （前提是需要在apps目录下操作）</span>scoop status <span class="c1"># 检查哪些软件有更新</span>scoop bucket known <span class="c1">#通过此命令列出已知所有 bucket（软件源）</span>scoop bucket add bucketName <span class="c1">#添加某个 bucket</span>scoop cache rm &lt;app&gt; <span class="c1"># 移除某个app的缓存</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><ul><li><p><strong>对于GUI程序</strong>，scoop会自动为其在开始菜单中添加快捷方式 ，路径： <code>C:\Users\Fan Dean\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Scoop Apps</code></p></li><li><p><strong>对于命令行程序</strong>，scoop会自动在 scoop应用安装路径下的 shims 文件夹下为其添加对应的exe程序，而shims文件夹是被添加到 PATH 变量中，所以可以直接在命令行中运行刚安装的程序。</p></li></ul><p><strong>安装 curl 、grep</strong></p><div data-lang="Code" class="language-code"><pre><code>scoop install curl grep</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><p>我们发现，下载的过程中自动下载了依赖7-zip。 在安装方面，它利用了7zip去解压安装包/压缩包，因此它对绿色软件有天生的友好属性。 。不仅如此，<strong>下载之后的内容会自动将加入到（Path）环境变量中</strong>。十分方便。大家都可以自己尝试为一些免安装软件建立软件源（需要安装的软件比较复杂，需要一定门槛）</p><blockquote><p>Scoop 是一个强大的工具，有着极大的可玩性、设计与实现理念，包括但不限于 <code>shim</code> 的软链接理念、利用 <code>persist</code> 存储<strong>用户数据</strong>等等，如果你感兴趣，请直接参考 <a href="https://github.com/lukesampson/scoop/wiki">Scoop 官方的 Wiki</a>。</p></blockquote><h2 id="添加软件源bucket">添加软件源Bucket<span class="anchor hide" data-clipboard-text="https://www.thisfaner.com/posts/devops/windows/scoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7/#添加软件源bucket" style="position: relative;"><span style="font-size: 1rem; position: absolute; top: 50%; transform: translateY(-50%); right: -2rem;">🔗</span></span></h2><p>Scoop说自己的软件源为Bucket，也可以称其为软件源或仓库。</p><p>参考：</p><ul><li><a href="https://github.com/lukesampson/scoop/wiki/Buckets#creating-your-own-bucket" title="Buckets · lukesampson/scoop Wiki">Buckets · lukesampson/scoop Wiki</a></li></ul><div data-lang="Code" class="language-code"><pre><code># bucket的用法scoop bucket add|list|known|rm [&lt;args&gt;]</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><p>一个添加第三方bucket的示例：</p><div data-lang="Code" class="language-code"><pre><code>scoop bucket add dorado https://github.com/h404bi/dorado</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><p>明确指定安装此软件源中的的程序</p><div data-lang="Code" class="language-code"><pre><code>scoop install dorado/&lt;app_name&gt;# 下面是dorado中特有的软件，测试其是否添加成功scoop search trash</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><p>推荐的Bucket：</p><ul><li><code>extras</code>：Scoop 官方维护的一个仓库，涵盖了大部分因为种种原因不能被收录进主仓库的常用软件。地址：<a href="https://github.com/lukesampson/scoop-extras/tree/master/bucket">lukesampson/scoop-extras</a></li><li><code>nirsoft</code>：是一个 NirSoft 开发的小工具的安装合集。NirSoft 制作了大量的（dozens and dozens）小工具，包括系统工具、网络工具、密码恢复等等，孜孜不倦、持续更新。<ul><li>Bucket 地址：<a href="https://github.com/kodybrown/scoop-nirsoft">kodybrown/scoop-nirsoft</a></li><li>NirSoft 官网地址：<a href="https://www.nirsoft.net/">NirSoft</a></li></ul></li><li>dorado（对中文支持更好）<a href="https://github.com/h404bi/dorado">h404bi/dorado: 🐟 A bucket of Scoop, for h404bi</a></li><li>ash258：<a href="https://github.com/Ash258/scoop-Ash258">Ash258/scoop-Ash258: Personal bucket with wide variety of applications of all kind.</a></li><li>java：</li><li>nerd-fonts ：包含各种字体</li></ul><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span><span class="lnt">7</span><span class="lnt">8</span><span class="lnt">9</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell"><span class="c1"># 先添加bucket</span>scoop bucket add extrasscoop bucket add nirsoftscoop bucket add dorado https://github.com/h404bi/doradoscoop bucket add Ash258 <span class="s1">'https://github.com/Ash258/Scoop-Ash258.git'</span>scoop bucket add nerd-fonts<span class="c1"># 对于开发人员，可添加</span>scoop bucket add javascoop bucket add versions</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><h2 id="bucket更新时遇到问题">bucket更新时遇到问题<span class="anchor hide" data-clipboard-text="https://www.thisfaner.com/posts/devops/windows/scoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7/#bucket更新时遇到问题" style="position: relative;"><span style="font-size: 1rem; position: absolute; top: 50%; transform: translateY(-50%); right: -2rem;">🔗</span></span></h2><p>由于extras bucket更新时遇到问题，我将其删除后再添加提示成功，但是它却把 main bucket及默认的bucket给删除了。通过"scoop status"检查状态时出现"These app manifests have been removed"并且下面列出了已被移除的软件名单。<strong>那么如何将 main bucket重新添加进来？</strong></p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span><span class="lnt">11</span><span class="lnt">12</span><span class="lnt">13</span><span class="lnt">14</span><span class="lnt">15</span><span class="lnt">16</span><span class="lnt">17</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">scoop <span class="nb">help</span> bucketscoop bucket known <span class="c1">#通过此命令列出已知所有 bucket</span><p>$ scoop bucket known <span class="c1"># 示列</span><br>main<br>extras<br>versions<br>nightlies<br>nirsoft<br>php<br>nerd-fonts<br>nonportable<br>java<br>games<br>jetbrains</p><p>scoop bucket add main <span class="c1">#添加 main bucket</span><br></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></p></div></div><h2 id="网络问题安装失败">网络问题安装失败<span class="anchor hide" data-clipboard-text="https://www.thisfaner.com/posts/devops/windows/scoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7/#网络问题安装失败" style="position: relative;"><span style="font-size: 1rem; position: absolute; top: 50%; transform: translateY(-50%); right: -2rem;">🔗</span></span></h2><p>比如安装irfanview一直失败，查看信息</p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span><span class="lnt">2</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">ERROR Download failed! <span class="o">(</span>Error 1<span class="o">)</span> An unknown error occurredERROR https://www.irfanview.info/files/iview453_x64.zip</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><p>看另一个示例：</p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">scoop install mediainfo</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><p>也是下载不下来，从输出信息中可以看到如下内容</p><div data-lang="Code" class="language-code"><pre><code>ERROR Download failed! (Error 1) An unknown error occurredERROR https://mediaarea.net/download/binary/mediainfo/19.09/MediaInfo_CLI_19.09_Windows_x64.zip    referer=https://mediaarea.net/download/binary/mediainfo/19.09/    dir=D:\Scoop\Applications\cache    out=mediainfo#19.09#https_mediaarea.net_download_binary_mediainfo_19.09_MediaInfo_CLI_19.09_Windows_x64.zip<p>ERROR &amp; ‘D:\Scoop\Applications\apps\aria2\current\aria2c.exe’ –input-file=’D:\Scoop\Applications\cache\mediainfo.txt’<br></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><p>我们可以发现文件的下载路径和下载后的文件名称，这里 <code>out=</code> 后面的压缩包就是下载后文件的名称，(也可以在 mediainfo.txt 中找到)</p></p><p>然后我们可以尝试在浏览器下载该程序，再更改文件名放入 sxoop 的 cache 目录，最后再次运行 scoop install mediainfo 即可安装。</p><hr><blockquote><p>下面的内容只是个人的一些记录，还有待补充和完善</p></blockquote><h2 id="已安装软件列表">已安装软件列表<span class="anchor hide" data-clipboard-text="https://www.thisfaner.com/posts/devops/windows/scoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7/#已安装软件列表" style="position: relative;"><span style="font-size: 1rem; position: absolute; top: 50%; transform: translateY(-50%); right: -2rem;">🔗</span></span></h2><p>添加额外的extras bucket：</p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">scoop bucket add extras</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><p>离线文档查看 zeal ：可集成到 idea 等</p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">λ scoop install zeal</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><p><strong>视频播放器 mpv</strong></p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">λ scoop install mpv</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><p><strong>文件同步工具 syncthing</strong>，在GitHub上超级火爆</p><div class="highlight"><div class="chroma"><table class="lntable"><tbody><tr><td class="lntd"><div data-lang="Code" class="language-code"><pre class="chroma"><code><span class="lnt">1</span></code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></td><td class="lntd"><pre class="chroma"><code class="language-shell" data-lang="shell">λ scoop install syncthing</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></td></tr></tbody></table></div></div><p><strong>ImageMagick 看图软件</strong>可以安装其替代品 GraphicsMagick</p><p>SVN</p><div data-lang="Code" class="language-code"><pre><code>scoop install sliksvnscoop install xx-net</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><p><strong>idea-ultimate：</strong></p><div data-lang="Code" class="language-code"><pre><code>scoop install idea-ultimate</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><div data-lang="Code" class="language-code"><pre><code>scoop install sumatrapdf</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div><h2 id="推荐的软件">推荐的软件<span class="anchor hide" data-clipboard-text="https://www.thisfaner.com/posts/devops/windows/scoop%25E5%258C%2585%25E7%25AE%25A1%25E7%2590%2586%25E5%25B7%25A5%25E5%2585%25B7/#推荐的软件" style="position: relative;"><span style="font-size: 1rem; position: absolute; top: 50%; transform: translateY(-50%); right: -2rem;">🔗</span></span></h2><blockquote><p>这里记录了Github上各种bucket，<a href="https://github.com/rasa/scoop-directory">rasa/scoop-directory: A directory of buckets for the scoop package manager for Windows</a> 相当于Scoop的第三方软件源。</p></blockquote><p>新机安装顺序：</p><ul><li>可选：Google官网下载Chrome下载器</li><li>先安装 scoop，将其配置好；再为scoop添加下面几个软件源：extras、dorado（对中文支持更好）、ash258、java</li><li>通过scoop安装cmder（或者安装WindowsTerminal）、RunAny（第一次使用scoop安装其他程序时就会自动安装7z）</li><li>通过scoop安装必要软件</li></ul><p>按安装方式进行分类</p><p>下载exe安装包安装：</p><ul><li><p>Firefox：使用scoop下载的话会出现无法更改语言和添加插件；使用PortableApp下载速度又贼慢</p><p>Firefox最新版本下载：根据此处（<a href="https://ftp.mozilla.org/pub/firefox/releases/latest/README.txt">latest Firefox release</a>）说明，拼出下面的下载地址（Win64，简体中文）</p><div data-lang="Code" class="language-code"><pre><code>https://download.mozilla.org/?product=firefox-latest&amp;os=win64&amp;lang=zh-CN</code></pre><span class="copy-to-clipboard" title="Copy to clipboard"></span></div></li><li><p>Chrome浏览器：直接在官网下载（是一个安装器），通过安装器安装的Chrome在之后更新时无需翻墙</p></li></ul><p>通过压缩包安装：</p><ul><li><a href="https://www.iplaysoft.com/runany.html">RunAny - 开源免费“一劳永逸”的热键快速启动工具 </a> 非常不错的工具，它的快捷键是`，如果要在文件中输入它，需要先按 “win”键。</li><li>ZoomIt：用作教鞭。通过Scoop无法安装它。ZoomIt是由微软工作人员开发的 <a href="https://docs.microsoft.com/en-us/sysinternals/downloads/">Sysinternals Utilities</a> 系列中的一个，我们也可以选择通过scoop安装所有工具</li></ul><p>通过Scoop安装：</p><ul><li>Cmder：Windows下替代cmd的终端</li><li>各种可在命令行使用的开发相关的程序</li><li>geekuninstaller：著名的卸载工具，能够完全清理卸载残留</li><li>vscode-portable ：VS code 在scoop中已经有绿色版</li><li>qbittorrent：BT下载软件</li><li>notepadplusplus：替代默认记事本的程序</li><li>7-zip：</li><li>uGet：简洁无广告的下载工具（Linux上可用）</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> cmder </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>解决VSCode报错</title>
      <link href="ide/vscode-terminal/"/>
      <url>ide/vscode-terminal/</url>
      
        <content type="html"><![CDATA[<p>很多小伙伴在使用VSCODE自带的terminal的时候会报出”系统禁止脚本运行的错误”,</p><p>小编找了下原因，是因为PowerShell执行策略的问题。</p><p>解决方法：</p><ol><li>以管理员身份运行vscode;</li><li>执行：get-ExecutionPolicy，显示Restricted，表示状态是禁止的;</li><li>执行：set-ExecutionPolicy RemoteSigned;</li><li>这时再执行get-ExecutionPolicy，就显示RemoteSigned;</li></ol><p>之后就不再有问题。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Go语言的核心特性</title>
      <link href="golang/golang-feature/"/>
      <url>golang/golang-feature/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.qfgolang.com/?special=rumenjianjie">https://www.qfgolang.com/?special=rumenjianjie</a></p><p>Go语言，作为编程语言的后生，站在巨人的肩膀上，吸收了其他一些编程语言的特点。</p><p>Go 编程语言是一个开源项目，它使程序员更具生产力。Go 语言具有很强的表达能力，它简洁、清晰而高效。得益于其并发机制， 用它编写的程序能够非常有效地利用多核与联网的计算机，其新颖的类型系统则使程序结构变得灵活而模块化。 Go 代码编译成机器码不仅非常迅速，还具有方便的垃圾收集机制和强大的运行时反射机制。 它是一个快速的、静态类型的编译型语言，感觉却像动态类型的解释型语言。(摘取自官网)</p><h2 id="一、思想"><a href="#一、思想" class="headerlink" title="一、思想"></a>一、思想</h2><p>Less can be more</p><p>大道至简,小而蕴真</p><p>让事情变得复杂很容易，让事情变得简单才难</p><p>深刻的工程文化</p><h2 id="二、核心特性"><a href="#二、核心特性" class="headerlink" title="二、核心特性"></a>二、核心特性</h2><p>Go语言之所以厉害，是因为它在服务端的开发中，总能抓住程序员的痛点，以最直接、简单、高效、稳定的方式来解决问题。这里我们并不会深入讨论GO语言的具体语法，只会将语言中关键的、对简化编程具有重要意义的方面介绍给大家，体验Go的核心特性。</p><h3 id="2-1-并发编程"><a href="#2-1-并发编程" class="headerlink" title="2.1 并发编程"></a>2.1 并发编程</h3><p>Go语言在并发编程方面比绝大多数语言要简洁不少，这一点是其最大亮点之一，也是其在未来进入高并发高性能场景的重要筹码。</p><p><img src= "/img/loading.gif" data-lazy-src="img/bingfa1.jpg" alt="bingfa1"></p><p>不同于传统的多进程或多线程，golang的并发执行单元是一种称为goroutine的协程。</p><p>由于在共享数据场景中会用到锁，再加上GC，其并发性能有时不如异步复用IO模型，因此相对于大多数语言来说，golang的并发编程简单比并发性能更具卖点。</p><p>在当今这个多核时代，并发编程的意义不言而喻。当然，很多语言都支持多线程、多进程编程，但遗憾的是，实现和控制起来并不是那么令人感觉轻松和愉悦。Golang不同的是，语言级别支持协程(goroutine)并发（协程又称微线程，比线程更轻量、开销更小，性能更高），操作起来非常简单，语言级别提供关键字（go）用于启动协程，并且在同一台机器上可以启动成千上万个协程。协程经常被理解为轻量级线程，一个线程可以包含多个协程，共享堆不共享栈。协程间一般由应用程序显式实现调度，上下文切换无需下到内核层，高效不少。协程间一般不做同步通讯，而golang中实现协程间通讯有两种：1）共享内存型，即使用全局变量+mutex锁来实现数据共享；2）消息传递型，即使用一种独有的channel机制进行异步通讯。</p><p>对比JAVA的多线程和GO的协程实现，明显更直接、简单。这就是GO的魅力所在，以简单、高效的方式解决问题，关键字go，或许就是GO语言最重要的标志。</p><p><strong>高并发是Golang语言最大的亮点</strong></p><h3 id="2-2-内存回收-GC"><a href="#2-2-内存回收-GC" class="headerlink" title="2.2 内存回收(GC)"></a>2.2 内存回收(GC)</h3><p>从C到C++，从程序性能的角度来考虑，这两种语言允许程序员自己管理内存，包括内存的申请和释放等。因为没有垃圾回收机制所以C/C++运行起来速度很快，但是随着而来的是程序员对内存使用上的很谨小慎微的考虑。因为哪怕一点不小心就可能会导致“内存泄露”使得资源浪费或者“野指针”使得程序崩溃等，尽管C++11后来使用了智能指针的概念，但是程序员仍然需要很小心的使用。后来为了提高程序开发的速度以及程序的健壮性，java和C#等高级语言引入了GC机制，即程序员不需要再考虑内存的回收等，而是由语言特性提供垃圾回收器来回收内存。但是随之而来的可能是程序运行效率的降低。 </p><p>GC过程是：先stop the world，扫描所有对象判活，把可回收对象在一段bitmap区中标记下来，接着立即start the world，恢复服务，同时起一个专门gorountine回收内存到空闲list中以备复用，不物理释放。物理释放由专门线程定期来执行。</p><p>GC瓶颈在于每次都要扫描所有对象来判活，待收集的对象数目越多，速度越慢。一个经验值是扫描10w个对象需要花费1ms，所以尽量使用对象少的方案，比如我们同时考虑链表、map、slice、数组来进行存储，链表和map每个元素都是一个对象，而slice或数组是一个对象，因此slice或数组有利于GC。</p><p>GC性能可能随着版本不断更新会不断优化，这块没仔细调研，团队中有HotSpot开发者，应该会借鉴jvm gc的设计思想，比如分代回收、safepoint等。</p><ul><li>内存自动回收，再也不需要开发人员管理内存</li><li>开发人员专注业务实现，降低了心智负担</li><li>只需要new分配内存，不需要释放</li></ul><h3 id="2-3-内存分配"><a href="#2-3-内存分配" class="headerlink" title="2.3 内存分配"></a>2.3 内存分配</h3><p>初始化阶段直接分配一块大内存区域，大内存被切分成各个大小等级的块，放入不同的空闲list中，对象分配空间时从空闲list中取出大小合适的内存块。内存回收时，会把不用的内存重放回空闲list。空闲内存会按照一定策略合并，以减少碎片。</p><h3 id="2-4-编译"><a href="#2-4-编译" class="headerlink" title="2.4 编译"></a>2.4 编译</h3><p>编译涉及到两个问题：编译速度和依赖管理</p><p>目前Golang具有两种编译器，一种是建立在GCC基础上的Gccgo，另外一种是分别针对64位x64和32位x86计算机的一套编译器(6g和8g)。</p><p>依赖管理方面，由于golang绝大多数第三方开源库都在github上，在代码的import中加上对应的github路径就可以使用了，库会默认下载到工程的pkg目录下。</p><p>另外，编译时会默认检查代码中所有实体的使用情况，凡是没使用到的package或变量，都会编译不通过。这是golang挺严谨的一面。</p><h3 id="2-5-网络编程"><a href="#2-5-网络编程" class="headerlink" title="2.5 网络编程"></a>2.5 网络编程</h3><p>由于golang诞生在互联网时代，因此它天生具备了去中心化、分布式等特性，具体表现之一就是提供了丰富便捷的网络编程接口，比如socket用net.Dial(基于tcp/udp，封装了传统的connect、listen、accept等接口)、http用http.Get/Post()、rpc用client.Call(‘class_name.method_name’, args, &amp;reply)，等等。</p><blockquote><p>高性能HTTP Server</p></blockquote><h3 id="2-6-函数多返回值"><a href="#2-6-函数多返回值" class="headerlink" title="2.6 函数多返回值"></a>2.6 函数多返回值</h3><p>在C，C++中，包括其他的一些高级语言是不支持多个函数返回值的。但是这项功能又确实是需要的，所以在C语言中一般通过将返回值定义成一个结构体，或者通过函数的参数引用的形式进行返回。而在Go语言中，作为一种新型的语言，目标定位为强大的语言当然不能放弃对这一需求的满足，所以支持函数多返回值是必须的。</p><p>函数定义时可以在入参后面再加(a,b,c)，表示将有3个返回值a、b、c。这个特性在很多语言都有，比如python。</p><p>这个语法糖特性是有现实意义的，比如我们经常会要求接口返回一个三元组（errno,errmsg,data），在大多数只允许一个返回值的语言中，我们只能将三元组放入一个map或数组中返回，接收方还要写代码来检查返回值中包含了三元组，如果允许多返回值，则直接在函数定义层面上就做了强制，使代码更简洁安全。</p><h3 id="2-7-语言交互性"><a href="#2-7-语言交互性" class="headerlink" title="2.7 语言交互性"></a>2.7 语言交互性</h3><p>语言交互性指的是本语言是否能和其他语言交互，比如可以调用其他语言编译的库。</p><p>在Go语言中直接重用了大部份的C模块，这里称为Cgo.Cgo允许开发者混合编写C语言代码，然后Cgo工具可以将这些混合的C代码提取并生成对于C功能的调用包装代码。开发者基本上可以完全忽略这个Go语言和C语言的边界是如何跨越的。</p><p> golang可以和C程序交互，但不能和C++交互。可以有两种替代方案：1）先将c++编译成动态库，再由go调用一段c代码，c代码通过dlfcn库动态调用动态库（记得export LD_LIBRARY_PATH）；2）使用swig(没玩过)</p><h3 id="2-8-异常处理"><a href="#2-8-异常处理" class="headerlink" title="2.8 异常处理"></a>2.8 异常处理</h3><p>golang不支持try…catch这样的结构化的异常解决方式，因为觉得会增加代码量，且会被滥用，不管多小的异常都抛出。golang提倡的异常处理方式是：</p><ul><li>普通异常：被调用方返回error对象，调用方判断error对象。</li><li>严重异常：指的是中断性panic（比如除0），使用defer…recover…panic机制来捕获处理。严重异常一般由golang内部自动抛出，不需要用户主动抛出，避免传统try…catch写得到处都是的情况。当然，用户也可以使用panic(‘xxxx’)主动抛出，只是这样就使这一套机制退化成结构化异常机制了。</li></ul><h3 id="2-9-其他一些有趣的特性"><a href="#2-9-其他一些有趣的特性" class="headerlink" title="2.9 其他一些有趣的特性"></a>2.9 其他一些有趣的特性</h3><ul><li><p>类型推导：类型定义：支持<code>var abc = 10</code>这样的语法，让golang看上去有点像动态类型语言，但golang实际上时强类型的，前面的定义会被自动推导出是int类型。</p><blockquote><p>作为强类型语言，隐式的类型转换是不被允许的，记住一条原则：让所有的东西都是显式的。</p><p>简单来说，Go是一门写起来像动态语言，有着动态语言开发效率的静态语言。</p></blockquote></li><li><p>一个类型只要实现了某个interface的所有方法，即可实现该interface，无需显式去继承。</p><blockquote><p>Go编程规范推荐每个Interface只提供一到两个的方法。这样使得每个接口的目的非常清晰。另外Go的隐式推导也使得我们组织程序架构的时候更加灵活。在写JAVA／C++程序的时候，我们一开始就需要把父类／子类／接口设计好，因为一旦后面有变更，修改起来会非常痛苦。而Go不一样，当你在实现的过程中发现某些方法可以抽象成接口的时候，你直接定义好这个接口就OK了，其他代码不需要做任何修改，编译器的自动推导会帮你做好一切。</p></blockquote></li><li><p>不能循环引用：即如果a.go中import了b，则b.go要是import a会报import cycle not allowed。好处是可以避免一些潜在的编程危险，比如a中的func1()调用了b中的func2()，如果func2()也能调用func1()，将会导致无限循环调用下去。</p></li><li><p>defer机制：在Go语言中，提供关键字defer，可以通过该关键字指定需要延迟执行的逻辑体，即在函数体return前或出现panic时执行。这种机制非常适合善后逻辑处理，比如可以尽早避免可能出现的资源泄漏问题。</p><p>可以说言描述上显得更为自然，极大的增强了代，defer是继goroutine和channel之后的另一个非常重要、实用的语言特性，对defer的引入，在很大程度上可以简化编程，并且在语码的可读性。</p></li><li><p>“包”的概念：和python一样，把相同功能的代码放到一个目录，称之为包。包可以被其他包引用。main包是用来生成可执行文件，每个程序只有一个main包。包的主要用途是提高代码的可复用性。通过package可以引入其他包。</p></li><li><p>编程规范：GO语言的编程规范强制集成在语言中，比如明确规定花括号摆放位置，强制要求一行一句，不允许导入没有使用的包，不允许定义没有使用的变量，提供gofmt工具强制格式化代码等等。奇怪的是，这些也引起了很多程序员的不满，有人发表GO语言的XX条罪状，里面就不乏对编程规范的指责。要知道，从工程管理的角度，任何一个开发团队都会对特定语言制定特定的编程规范，特别像Google这样的公司，更是如此。GO的设计者们认为，与其将规范写在文档里，还不如强制集成在语言里，这样更直接，更有利用团队协作和工程管理。</p></li><li><p>交叉编译：比如说你可以在运行 Linux 系统的计算机上开发运行 Windows 下运行的应用程序。这是第一门完全支持 UTF-8 的编程语言，这不仅体现在它可以处理使用 UTF-8 编码的字符串，就连它的源码文件格式都是使用的 UTF-8 编码。Go 语言做到了真正的国际化！</p></li></ul><h2 id="三、功能"><a href="#三、功能" class="headerlink" title="三、功能"></a>三、功能</h2><p>此处我们说个小段子：(引自网上某篇文章，具体是哪一篇想不起来了)</p><p>很久以前，有一个IT公司，这公司有个传统，允许员工拥有20%自由时间来开发实验性项目。在2007的某一天，公司的几个大牛，正在用c++开发一些比较繁琐但是核心的工作，主要包括庞大的分布式集群，大牛觉得很闹心，后来c++委员会来他们公司演讲，说c++将要添加大概35种新特性。这几个大牛的其中一个人，名为：Rob Pike，听后心中一万个xxx飘过，“c++特性还不够多吗？简化c++应该更有成就感吧”。于是乎，Rob Pike和其他几个大牛讨论了一下，怎么解决这个问题，过了一会，Rob Pike说要不我们自己搞个语言吧，名字叫“go”，非常简短，容易拼写。其他几位大牛就说好啊，然后他们找了块白板，在上面写下希望能有哪些功能。接下来的时间里，大牛们开心的讨论设计这门语言的特性，经过漫长的岁月，他们决定，以c语言为原型，以及借鉴其他语言的一些特性，来解放程序员，解放自己，然后在2009年，go语言诞生。</p><p>以下就是这些大牛所罗列出的Go要有的功能：</p><ul><li>规范的语法（不需要符号表来解析）</li><li>垃圾回收（独有）</li><li>无头文件</li><li>明确的依赖</li><li>无循环依赖</li><li>常量只能是数字</li><li>int和int32是两种类型</li><li>字母大小写设置可见性（letter case sets visibility）</li><li>任何类型（type）都有方法（不是类型）</li><li>没有子类型继承（不是子类）</li><li>包级别初始化以及明确的初始化顺序</li><li>文件被编译到一个包里</li><li>包package-level globals presented in any order</li><li>没有数值类型转换（常量起辅助作用）</li><li>接口隐式实现（没有“implement”声明）</li><li>嵌入（不会提升到超类）</li><li>方法按照函数声明（没有特别的位置要求）</li><li>方法即函数</li><li>接口只有方法（没有数据）</li><li>方法通过名字匹配（而非类型）</li><li>没有构造函数和析构函数</li><li>postincrement（如++i）是状态，不是表达式</li><li>没有preincrement(i++)和predecrement</li><li>赋值不是表达式</li><li>明确赋值和函数调用中的计算顺序（没有“sequence point”）</li><li>没有指针运算</li><li>内存一直以零值初始化</li><li>局部变量取值合法</li><li>方法中没有“this”</li><li>分段的堆栈</li><li>没有静态和其它类型的注释</li><li>没有模板</li><li>内建string、slice和map</li><li>数组边界检查</li></ul><blockquote><h2 id="大牛真身"><a href="#大牛真身" class="headerlink" title="大牛真身"></a>大牛真身</h2><p>最大牌的当属B和C语言设计者、Unix和Plan 9创始人、1983年图灵奖获得者Ken Thompson，这份名单中还包括了Unix核心成员Rob Pike（go语言之父）、java HotSpot虚拟机和js v8引擎的开发者Robert Griesemer、Memcached作者Brad Fitzpatrick，等等。</p></blockquote><h1 id="Go1-16新特性"><a href="#Go1-16新特性" class="headerlink" title="Go1.16新特性"></a>Go1.16新特性</h1><h2 id="1-泛型"><a href="#1-泛型" class="headerlink" title="1. 泛型"></a>1. 泛型</h2>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>django面试题</title>
      <link href="python/Django/django-interview1/"/>
      <url>python/Django/django-interview1/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.jianshu.com/p/724233387ba3">https://www.jianshu.com/p/724233387ba3</a></p><h2 id="1-什么是WSGI"><a href="#1-什么是WSGI" class="headerlink" title="1. 什么是WSGI"></a>1. 什么是WSGI</h2><p>wsgi是python 处理http请求时，规定的一种处理方式。如一个HTTP request 过来了，name就有一个相应的处理函数来进行处理和返回结果。WSGI就是规定这个处理函数的参数长啥样的，他的返回结果是啥样的？至于该处理函数的名字和处理逻辑是啥样的，那就无所谓了。简单而言，WSGI就是规定了处理函数的输入和输出格式。</p><h2 id="2-django请求生命周期？"><a href="#2-django请求生命周期？" class="headerlink" title="2. django请求生命周期？"></a>2. django请求生命周期？</h2><ul><li>当用户在浏览器中输入url时，浏览器会生成请求头和请求体发给服务端，请求头和请求体中会包含浏览器的动作（action），这个动作通常为get或者post，体现在url之中。</li><li>url经过django中的WSGI，在经过Django的中间件，最后URL到过路由映射表，在路由中一条一条进行匹配，一旦其中一条匹配成功就执行对应的视图函数，后面的路由就不在继续匹配了。</li><li>视图函数根据客户端的请求查询相应的数据，返回给Django，然后Django吧客户端想要的数据作为一个字符串返回给客户端。</li><li>客户端浏览器接受到返回的数据，经过渲染后显示给客户/用户</li></ul><h2 id="3-列举django的内置组件"><a href="#3-列举django的内置组件" class="headerlink" title="3. 列举django的内置组件"></a>3. 列举django的内置组件</h2><ul><li>admin（django自带的后台）是对model中对应的数据表进行增删改查提供的组件</li><li>model组件：负责操作数据库</li><li>form组件：1.生成HTML代码，2数据有效性校验，3 校验信息返回并展示</li><li>ModelForm组件即用于数据库操作，也可用于用户请求的验证</li></ul><h2 id="4-列举django中间件的5个方法？以及django中间件的应用场景"><a href="#4-列举django中间件的5个方法？以及django中间件的应用场景" class="headerlink" title="4.列举django中间件的5个方法？以及django中间件的应用场景"></a>4.列举django中间件的5个方法？以及django中间件的应用场景</h2><ul><li>process_request:请求进来时,权限认证</li><li>process_view:路由匹配之后,能够得到视图函数</li><li>process_exception: 异常时执行</li><li>process_template_responseprocess: 模板渲染时执行</li><li>process_response:请求有响应时执行</li></ul><h2 id="5-简述什么是FBV和CBV？"><a href="#5-简述什么是FBV和CBV？" class="headerlink" title="5. 简述什么是FBV和CBV？"></a>5. 简述什么是FBV和CBV？</h2><p>FBV和CBV本质是一样的，基于函数的视图叫做FBV，基于类的视图叫做CBV</p><p>在python中使用CBV的优点：</p><ul><li>提高了代码的复用性</li><li>可以用不同的函数针对不同的HTTP方法处理，而不是通过很多if判断，提高代码可读性</li></ul><h2 id="6-django的request对象在什么时候创建的？"><a href="#6-django的request对象在什么时候创建的？" class="headerlink" title="6. django的request对象在什么时候创建的？"></a>6. django的request对象在什么时候创建的？</h2><p>class WSGIHandler(base.BaseHandler):<br>——-request = self.request_class(environ)<br>请求走到WSGIHandler类的时候，执行cell方法，将environ封装成了request</p><h2 id="7、如何给CBV的程序添加装饰器？"><a href="#7、如何给CBV的程序添加装饰器？" class="headerlink" title="7、如何给CBV的程序添加装饰器？"></a>7、如何给CBV的程序添加装饰器？</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">from django.utils.decorators import method_decorator</span><br><span class="line">1、给方法加：</span><br><span class="line">    @method_decorator(check_login)</span><br><span class="line">    def post(self, request):</span><br><span class="line">        ...</span><br><span class="line">2、给dispatch加：</span><br><span class="line">    @method_decorator(check_login)</span><br><span class="line">    def dispatch(self, request, *args, **kwargs):</span><br><span class="line">        ...</span><br><span class="line">3、给类加：</span><br><span class="line">    @method_decorator(check_login, name&#x3D;&quot;get&quot;)</span><br><span class="line">    @method_decorator(check_login, name&#x3D;&quot;post&quot;)</span><br><span class="line">    class HomeView(View):</span><br><span class="line">        ...</span><br></pre></td></tr></table></figure><h2 id="8、列举django-orm-中所有的方法（QuerySet对象的所有方法）"><a href="#8、列举django-orm-中所有的方法（QuerySet对象的所有方法）" class="headerlink" title="8、列举django orm 中所有的方法（QuerySet对象的所有方法）"></a>8、列举django orm 中所有的方法（QuerySet对象的所有方法）</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&lt;<span class="number">1</span>&gt; all():                  查询所有结果 </span><br><span class="line">  &lt;<span class="number">2</span>&gt; filter(**kwargs):       它包含了与所给筛选条件相匹配的对象。获取不到返回None</span><br><span class="line">  &lt;<span class="number">3</span>&gt; get(**kwargs):          返回与所给筛选条件相匹配的对象，返回结果有且只有一个。</span><br><span class="line">                              如果符合筛选条件的对象超过一个或者没有都会抛出错误。</span><br><span class="line">  &lt;<span class="number">4</span>&gt; exclude(**kwargs):      它包含了与所给筛选条件不匹配的对象</span><br><span class="line">  &lt;<span class="number">5</span>&gt; order_by(*field):       对查询结果排序</span><br><span class="line">  &lt;<span class="number">6</span>&gt; reverse():              对查询结果反向排序 </span><br><span class="line">  &lt;<span class="number">8</span>&gt; count():                返回数据库中匹配查询(QuerySet)的对象数量。 </span><br><span class="line">  &lt;<span class="number">9</span>&gt; first():                返回第一条记录 </span><br><span class="line">  &lt;<span class="number">10</span>&gt; last():                返回最后一条记录 </span><br><span class="line">  &lt;<span class="number">11</span>&gt; exists():              如果QuerySet包含数据，就返回True，否则返回False</span><br><span class="line">  &lt;<span class="number">12</span>&gt; values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet，运行后得到的</span><br><span class="line">                              并不是一系 model的实例化对象，而是一个可迭代的字典序列</span><br><span class="line">  &lt;<span class="number">13</span>&gt; values_list(*field):   它与values()非常相似，它返回的是一个元组序列，values返回的是一个字典序列</span><br><span class="line">  &lt;<span class="number">14</span>&gt; distinct():            从返回结果中剔除重复纪录</span><br></pre></td></tr></table></figure><h2 id="9、select-related和prefetch-related的区别？"><a href="#9、select-related和prefetch-related的区别？" class="headerlink" title="9、select_related和prefetch_related的区别？"></a>9、select_related和prefetch_related的区别？</h2><p>前提：有外键存在时，可以很好的减少数据库请求的次数,提高性能<br>select_related通过多表join关联查询,一次性获得所有数据,只执行一次SQL查询<br>prefetch_related分别查询每个表,然后根据它们之间的关系进行处理,执行两次查询</p><h2 id="10、filter和exclude的区别？"><a href="#10、filter和exclude的区别？" class="headerlink" title="10、filter和exclude的区别？"></a>10、filter和exclude的区别？</h2><p>两者取到的值都是QuerySet对象,filter选择满足条件的,exclude:排除满足条件的.</p><h2 id="11、列举django-orm中三种能写sql语句的方法"><a href="#11、列举django-orm中三种能写sql语句的方法" class="headerlink" title="11、列举django orm中三种能写sql语句的方法"></a>11、列举django orm中三种能写sql语句的方法</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">1.使用execute执行自定义的SQL</span><br><span class="line">     直接执行SQL语句（类似于pymysql的用法）</span><br><span class="line">        # 更高灵活度的方式执行原生SQL语句</span><br><span class="line">        from django.db import connection</span><br><span class="line">        cursor &#x3D; connection.cursor()</span><br><span class="line">        cursor.execute(&quot;SELECT DATE_FORMAT(create_time, &#39;%Y-%m&#39;) FROM blog_article;&quot;)</span><br><span class="line">        ret &#x3D; cursor.fetchall()</span><br><span class="line">        print(ret)</span><br><span class="line">2.使用extra方法 ：queryset.extra(select&#x3D;&#123;&quot;key&quot;: &quot;原生的SQL语句&quot;&#125;)</span><br><span class="line">3.使用raw方法</span><br><span class="line">    1.执行原始sql并返回模型</span><br><span class="line">    2.依赖model多用于查询</span><br></pre></td></tr></table></figure><h2 id="12-values和values-list的区别？"><a href="#12-values和values-list的区别？" class="headerlink" title="12. values和values_list的区别？"></a>12. values和values_list的区别？</h2><ul><li>values : queryset类型的列表中是字典</li><li>values_list : queryset类型的列表中是元组</li></ul><h2 id="13、cookie和session的区别："><a href="#13、cookie和session的区别：" class="headerlink" title="13、cookie和session的区别："></a>13、cookie和session的区别：</h2><ul><li>cookie:<br>cookie是保存在浏览器端的键值对,可以用来做用户认证</li><li>session：<br>将用户的会话信息保存在服务端,key值是随机产生的字符串,value值是session的内容<br>依赖于cookie将每个用户的随机字符串保存到用户浏览器上</li><li>Django中session默认保存在数据库中：django_session表</li><li>flask,session默认将加密的数据写在用户的cookie中</li></ul><h2 id="14、如何使用django-orm批量创建数据？"><a href="#14、如何使用django-orm批量创建数据？" class="headerlink" title="14、如何使用django orm批量创建数据？"></a>14、如何使用django orm批量创建数据？</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">objs=[models.Book(title=<span class="string">&quot;图书&#123;&#125;&quot;</span>.<span class="built_in">format</span>(i+<span class="number">15</span>)) <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">100</span>)]</span><br><span class="line">models.Book.objects.bulk_create(objs)</span><br></pre></td></tr></table></figure><h2 id="16、django的Model中的ForeignKey字段中的on-delete参数有什么作用？"><a href="#16、django的Model中的ForeignKey字段中的on-delete参数有什么作用？" class="headerlink" title="16、django的Model中的ForeignKey字段中的on_delete参数有什么作用？"></a>16、django的Model中的ForeignKey字段中的on_delete参数有什么作用？</h2><p>删除关联表中的数据时,当前表与其关联的field的操作<br>django2.0之后，表与表之间关联的时候,必须要写on_delete参数,否则会报异常</p><h2 id="17、django的模板中自定义filter和simple-tag的区别？"><a href="#17、django的模板中自定义filter和simple-tag的区别？" class="headerlink" title="17、django的模板中自定义filter和simple_tag的区别？"></a>17、django的模板中自定义filter和simple_tag的区别？</h2><ul><li>自定义filter：{ { 参数1|filter函数名:参数2 } }</li></ul><p>1.可以与if标签来连用<br>2.自定义时需要写两个形参</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">例子：自定义filter</span><br><span class="line">    <span class="number">1.</span> 在app01下创建一个叫templatetags的Python包</span><br><span class="line">    <span class="number">2.</span> 在templatetags的文件夹下创建py文件  myfilters</span><br><span class="line">    <span class="number">3.</span> 在py文件中写代码</span><br><span class="line">        <span class="keyword">from</span> django <span class="keyword">import</span> template</span><br><span class="line">        register = template.Library()</span><br><span class="line">        </span><br><span class="line">        @register.filter</span><br><span class="line">        def add_sb(value,arg=<span class="string">&#x27;aaa&#x27;</span>):</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;&#123;&#125;_sb_&#123;&#125;&quot;</span>.formart(value,arg)</span><br><span class="line">            </span><br><span class="line">        @register.filter(name=<span class="string">&#x27;sb&#x27;</span>)</span><br><span class="line">        def add_sb(value,arg=<span class="string">&#x27;aaa&#x27;</span>):</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;&#123;&#125;_sb_&#123;&#125;&quot;</span>.formart(value,arg)     </span><br><span class="line">    <span class="number">4.</span> 使用自定义filter</span><br><span class="line">        &#123; % load myfilters % &#125;</span><br><span class="line">        &#123; &#123; name|add_sb:<span class="string">&#x27;xxx&#x27;</span>&#125; &#125;</span><br><span class="line">        &#123; &#123; name|sb:<span class="string">&#x27;xxx&#x27;</span>&#125; &#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>simple_tag:{ % simple_tag函数名 参数1 参数2 % }</li></ul><ol><li>可以传多个参数,没有限制</li><li>不能与if标签来连用</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">例子：自定义simpletag</span><br><span class="line">    创建</span><br><span class="line">        <span class="number">1</span> 、在app01中创建一个名字是templatetags的包，</span><br><span class="line">        <span class="number">2</span>、在包中创建一个py文件</span><br><span class="line">        <span class="number">3</span>、在py文件中导入</span><br><span class="line">              <span class="keyword">from</span> django <span class="keyword">import</span> template</span><br><span class="line">              register = template.Library()</span><br><span class="line">        <span class="number">4</span>、写函数</span><br><span class="line">              @register.simple_tag(name=<span class="string">&quot;plus&quot;</span>)</span><br><span class="line">              def plus(a,b,c):</span><br><span class="line">                  <span class="keyword">return</span> <span class="string">&#x27;&#123;&#125;+&#123;&#125;+&#123;&#125;&#x27;</span>.format(a,b,c)</span><br><span class="line">        <span class="number">5</span>、加装饰器@register.simple_tag(name=<span class="string">&quot;plus&quot;</span>)</span><br><span class="line">  使用</span><br><span class="line">      <span class="number">1</span>、导入</span><br><span class="line">            &#123; % load mytag % &#125;</span><br><span class="line">      <span class="number">2</span>、使用</span><br><span class="line">           &#123; % plus <span class="number">1</span> <span class="number">2</span> <span class="number">3</span> % &#125;</span><br></pre></td></tr></table></figure><h2 id="18-django-中csrf-的实现机制"><a href="#18-django-中csrf-的实现机制" class="headerlink" title="18 django 中csrf 的实现机制"></a>18 django 中csrf 的实现机制</h2><ul><li><p>第一步：django第一次响应来自某个客户端的请求时，后端随机产生一个token值，把这个token保存在session状态中；同时，后端把这个token放到cookie中交给前端页面；</p></li><li><p>第二部：下次前端页面需要发起请求（比如发帖）的时候把这个token值加入到请求数据或者头信息中，一起传给后端；Cookie：{ csrftoken：xxxxx}</p></li><li><p>第三部：后端校验前端请求带过来的token和session里的token是否一致。</p></li></ul><h2 id="19，基于django使用ajax发送post请求时，都可以使用哪种方法携带csrf-token"><a href="#19，基于django使用ajax发送post请求时，都可以使用哪种方法携带csrf-token" class="headerlink" title="19，基于django使用ajax发送post请求时，都可以使用哪种方法携带csrf token"></a>19，基于django使用ajax发送post请求时，都可以使用哪种方法携带csrf token</h2><ol><li>后端将csrftoken传到前端，发送post请求时携带这个值发送<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">data: &#123;</span><br><span class="line">        csrfmiddlewaretoken: &#39;&#123; &#123; csrf_token &#125; &#125;&#39;</span><br><span class="line">  &#125;,</span><br></pre></td></tr></table></figure></li><li>获取form中隐藏标签的csrftoken值，加入到请求数据中传给后端<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">data: &#123;</span><br><span class="line">          csrfmiddlewaretoken:$(&#39;[name&#x3D;&quot;csrfmiddlewaretoken&quot;]&#39;).val()</span><br><span class="line">     &#125;,</span><br></pre></td></tr></table></figure></li><li>cookie中存在csrftoken,将csrftoken值放到请求头中<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">headers:&#123; &quot;X-CSRFtoken&quot;:$.cookie(&quot;csrftoken&quot;)&#125;</span><br></pre></td></tr></table></figure></li></ol><h2 id="20、runserver与uWSGI的区别"><a href="#20、runserver与uWSGI的区别" class="headerlink" title="20、runserver与uWSGI的区别"></a>20、runserver与uWSGI的区别</h2><p><strong>Django本身提供了runserver，为什么不能用来部署？</strong><br>1.runserver方法是调试 Django 时经常用到的运行方式，它使用Django自带的<br>WSGI Server 运行，主要在测试和开发中使用，并且 runserver 开启的方式也是单进程 。<br>2.uWSGI是一个Web服务器，它实现了WSGI协议、uwsgi、http 等协议。注意uwsgi是一种通信协议，而uWSGI是实现uwsgi协议和WSGI协议的 Web 服务器。uWSGI具有超快的性能、低内存占用和多app管理等优点，并且搭配着Nginx就是一个生产环境了，能够将用户访问请求与应用 app 隔离开，实现真正的部署 。相比来讲，支持的并发量更高，方便管理多进程，发挥多核的优势，提升性能。</p><h2 id="21、Django如何实现websocket？"><a href="#21、Django如何实现websocket？" class="headerlink" title="21、Django如何实现websocket？"></a>21、Django如何实现websocket？</h2><ul><li>django实现websocket官方推荐大家使用channels。channels通过升级http协议 升级到websocket协议。保证实时通讯。也就是说，我们完全可以用channels实现我们的即时通讯。而不是使用长轮询和计时器方式来保证伪实时通讯。他通过改造django框架，使django既支持http协议又支持websocket协议。</li><li>官方文档地址：<a href="https://channels.readthedocs.io/en/stable/">https://channels.readthedocs.io/en/stable/</a></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Nginx简介</title>
      <link href="comic/nginx/"/>
      <url>comic/nginx/</url>
      
        <content type="html"><![CDATA[<h2 id="什么是-Nginx"><a href="#什么是-Nginx" class="headerlink" title="什么是 Nginx"></a>什么是 Nginx</h2><p>Nginx 是俄罗斯人编写的十分轻量级的 HTTP 服务器,Nginx，它的发音为“engine X”，是一个高性能的HTTP和反向代理服务器，同时也是一个 IMAP/POP3/SMTP 代理服务器。Nginx 是由俄罗斯人 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的，它已经在该站点运行超过两年半了。Igor Sysoev 在建立的项目时,使用基于 BSD 许可。</p><p>英文主页：<a href="http://nginx.net/">http://nginx.net</a> 。</p><p>到 2013 年，目前有很多国内网站采用 Nginx 作为 Web 服务器，如国内知名的新浪、163、腾讯、Discuz、豆瓣等。据 netcraft 统计，Nginx 排名第 3，约占 15% 的份额(参见：<a href="http://news.netcraft.com/archives/category/web-server-survey/">http://news.netcraft.com/archives/category/web-server-survey/</a> )</p><p>Nginx 以事件驱动的方式编写，所以有非常好的性能，同时也是一个非常高效的反向代理、负载平衡。其拥有匹配 Lighttpd 的性能，同时还没有 Lighttpd 的内存泄漏问题，而且 Lighttpd 的 mod_proxy 也有一些问题并且很久没有更新。</p><p>现在，Igor 将源代码以类 BSD 许可证的形式发布。Nginx 因为它的稳定性、丰富的模块库、灵活的配置和低系统资源的消耗而闻名．业界一致认为它是 Apache2.2＋mod_proxy_balancer 的轻量级代替者，不仅是因为响应静态页面的速度非常快，而且它的模块数量达到 Apache 的近 2/3。对 proxy 和 rewrite 模块的支持很彻底，还支持 mod_fcgi、ssl、vhosts ，适合用来做 mongrel clusters 的前端 HTTP 响应。</p><h2 id="Nginx-特点"><a href="#Nginx-特点" class="headerlink" title="Nginx 特点"></a>Nginx 特点</h2><p>Nginx 做为 HTTP 服务器，有以下几项基本特性：</p><ul><li><p>处理静态文件，索引文件以及自动索引；打开文件描述符缓冲．</p></li><li><p>无缓存的反向代理加速，简单的负载均衡和容错．</p></li><li><p>FastCGI，简单的负载均衡和容错．</p></li><li><p>模块化的结构。包括 gzipping, byte ranges, chunked responses,以及 SSI-filter 等 filter。如果由 FastCGI 或其它代理服务器处理单页中存在的多个 SSI，则这项处理可以并行运行，而不需要相互等待。</p></li><li><p>支持 SSL 和 TLSSNI．</p></li></ul><p>Nginx 专为性能优化而开发，性能是其最重要的考量,实现上非常注重效率 。它支持内核 Poll 模型，能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数。</p><p>Nginx 具有很高的稳定性。其它 HTTP 服务器，当遇到访问的峰值，或者有人恶意发起慢速连接时，也很可能会导致服务器物理内存耗尽频繁交换，失去响应，只能重启服务器。例如当前 apache 一旦上到 200 个以上进程，web响应速度就明显非常缓慢了。而 Nginx 采取了分阶段资源分配技术，使得它的 CPU 与内存占用率非常低。Nginx 官方表示保持 10,000 个没有活动的连接，它只占 2.5M 内存，所以类似 DOS 这样的攻击对 Nginx 来说基本上是毫无用处的。就稳定性而言,Nginx 比 lighthttpd 更胜一筹。</p><p>Nginx 支持热部署。它的启动特别容易, 并且几乎可以做到 7*24 不间断运行，即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下，对软件版本进行进行升级。</p><p>Nginx 采用 master-slave 模型,能够充分利用 SMP 的优势，且能够减少工作进程在磁盘 I/O 的阻塞延迟。当采用 select()/poll() 调用时，还可以限制每个进程的连接数。</p><p>Nginx 代码质量非常高，代码很规范，手法成熟，模块扩展也很容易。特别值得一提的是强大的 Upstream 与 Filter 链。Upstream 为诸如 reverse proxy,与其他服务器通信模块的编写奠定了很好的基础。而 Filter 链最酷的部分就是各个 filter 不必等待前一个 filter 执行完毕。它可以把前一个 filter 的输出做为当前 filter 的输入，这有点像 Unix 的管线。这意味着，一个模块可以开始压缩从后端服务器发送过来的请求，且可以在模块接收完后端服务器的整个请求之前把压缩流转向客户端。</p><p>Nginx 采用了一些 os 提供的最新特性如对 sendfile (Linux2.2+)，accept-filter (FreeBSD4.1+)，TCP_DEFER_ACCEPT (Linux 2.4+)的支持，从而大大提高了性能。</p><p>当然，Nginx 还很年轻，多多少少存在一些问题，比如：Nginx 是俄罗斯人创建，虽然前几年文档比较少，但是目前文档方面比较全面，英文资料居多，中文的资料也比较多，而且有专门的书籍和资料可供查找。</p><p>Nginx 的作者和社区都在不断的努力完善，我们有理由相信 Nginx 将继续以高速的增长率来分享轻量级 HTTP 服务器市场，会有一个更美好的未来。</p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>浅谈Git 与 SVN 区别</title>
      <link href="git/git-svn/"/>
      <url>git/git-svn/</url>
      
        <content type="html"><![CDATA[<h1 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h1><p>SVN和Git是当下主流的版本控制工具，今天小编就带大家对比一下他们之间的区别与优缺点。</p><h1 id="SVN"><a href="#SVN" class="headerlink" title="SVN"></a>SVN</h1><h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><p>Subversion(SVN) 是一个开源的版本控制系統, 也就是说 Subversion 管理着随时间改变的数据。 这些数据放置在一个中央资料档案库(repository) 中。 这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变动。 这样你就可以把档案恢复到旧的版本, 或是浏览文件的变动历史。</p><h2 id="SVN的优点："><a href="#SVN的优点：" class="headerlink" title="SVN的优点："></a>SVN的优点：</h2><p>1、采用集中式，易于管理，保证安全性；</p><p>2、管理方便，逻辑明确，理念符合常规思维；</p><p>3、代码的一致性高；</p><p>4、适合人数不多的项目开发；</p><p>5、允许一个文件有任意多的可命名属性，会关注所有的文件类型；</p><p>6、支持二进制文件，更容易处理大文件；</p><p>7、支持空目录。</p><h2 id="SVN的缺点："><a href="#SVN的缺点：" class="headerlink" title="SVN的缺点："></a>SVN的缺点：</h2><p>1、服务器压力太大，数据库容量暴增；</p><p>2、必须连接在服务器上，否则基本不能工作、提交、对比、还原等；</p><p>3、不适合开源开发。</p><h1 id="Git"><a href="#Git" class="headerlink" title="Git"></a>Git</h1><h2 id="概念-1"><a href="#概念-1" class="headerlink" title="概念"></a>概念</h2><p>Git 是一个开源的分布式版本控制系统，用于敏捷高效地处理任何或小或大的项目。</p><p>Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。</p><p>Git 与常用的版本控制工具 CVS, Subversion 等不同，它采用了分布式版本库的方式，不必服务器端软件支持。</p><h2 id="Git的优点："><a href="#Git的优点：" class="headerlink" title="Git的优点："></a>Git的优点：</h2><p>1、适合分布式开发，强调个体；</p><p>2、公共的服务器压力和数量都不会太大；</p><p>3、速度快， 成熟的架构，开发灵活；</p><p>4、任意两个开发者之间可以很容易的解决冲突；</p><p>5、离线工作，管理代码成本低，不需要依赖服务器；</p><p>6、部署方便。基本上下个命令就可以用；</p><p>7、良好的分支机制，可以让主干代码保持干净。</p><h2 id="Git的缺点："><a href="#Git的缺点：" class="headerlink" title="Git的缺点："></a>Git的缺点：</h2><p>1、资料少，学习成本比较大，学习周期比较长，要求人员素质比较高；</p><p>2、不符合常规思维；</p><p>3、代码保密性差，一旦开发者把整个库克隆下来就可以完全公开所有代码和版本信息。</p><h1 id="Git-与-SVN-区别"><a href="#Git-与-SVN-区别" class="headerlink" title="Git 与 SVN 区别"></a>Git 与 SVN 区别</h1><p><img src= "/img/loading.gif" data-lazy-src="https://www.runoob.com/wp-content/uploads/2015/02/0D32F290-80B0-4EA4-9836-CA58E22569B3.jpg" alt="git vs  svn  "></p><p>Git 不仅仅是个版本控制系统，它也是个内容管理系统(CMS)，工作管理系统等。</p><p>如果你是一个具有使用 SVN 背景的人，你需要做一定的思想转换，来适应 Git 提供的一些概念和特征。</p><p>Git 与 SVN 区别点：</p><p>1、Git 是分布式的，SVN 不是：这是 Git 和其它非分布式的版本控制系统，例如 SVN，CVS 等，最核心的区别。</p><p>2、Git 把内容按元数据方式存储，而 SVN 是按文件：所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等的文件夹里。</p><p>3、Git 分支和 SVN 的分支不同：分支在 SVN 中一点都不特别，其实它就是版本库中的另外一个目录。</p><p>4、Git 没有一个全局的版本号，而 SVN 有：目前为止这是跟 SVN 相比 Git 缺少的最大的一个特征。</p><p>5、Git 的内容完整性要优于 SVN：Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性，确保在遇到磁盘故障和网络问题时降低对版本库的破坏。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Golang语言写99乘法表</title>
      <link href="golang/golang-99/"/>
      <url>golang/golang-99/</url>
      
        <content type="html"><![CDATA[<h3 id="1-标准写法"><a href="#1-标准写法" class="headerlink" title="1. 标准写法:"></a>1. 标准写法:</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> 表达式<span class="number">1</span>;表达式<span class="number">2</span>;表达式<span class="number">3</span>&#123;</span><br><span class="line">    循环体</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="2-同时省略表达式1和表达式3"><a href="#2-同时省略表达式1和表达式3" class="headerlink" title="2. 同时省略表达式1和表达式3"></a>2. 同时省略表达式1和表达式3</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> 表达式<span class="number">2</span>&#123;</span><br><span class="line">    循环体</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 相当于while(条件)</span></span><br></pre></td></tr></table></figure><h3 id="3-同时省略3个表达式"><a href="#3-同时省略3个表达式" class="headerlink" title="3. 同时省略3个表达式"></a>3. 同时省略3个表达式</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>&#123;</span><br><span class="line">    循环体</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 相当于while(true)</span></span><br><span class="line"><span class="comment">// 注意:当for循环中,省略了表达式2,就相当于直接作用在了true上</span></span><br></pre></td></tr></table></figure><h3 id="4-其他写法"><a href="#4-其他写法" class="headerlink" title="4. 其他写法"></a>4. 其他写法</h3><p>for循环中同时省略几个表达式都可以..</p><ul><li>省略表达式1:变量的初始定义要在外面</li><li>省略表达式2:循环永远成立-&gt;&gt;&gt;死循环</li><li>省略表达式3:变量的更新需要写着循环体里面,否则还是死循环</li></ul><h2 id="99乘法表程序"><a href="#99乘法表程序" class="headerlink" title="99乘法表程序"></a>99乘法表程序</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">循环语句</span></span><br><span class="line"><span class="comment">for 表达式1；表达式2；表达式3&#123;</span></span><br><span class="line"><span class="comment">循环体</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="number">10</span>; i++ &#123;</span><br><span class="line"><span class="keyword">for</span> j := <span class="number">1</span>; j&lt;i+<span class="number">1</span>; j++&#123;</span><br><span class="line">fmt.Print(i,<span class="string">&quot;*&quot;</span>,j,<span class="string">&quot;=&quot;</span>,i*j)</span><br><span class="line">fmt.Print(<span class="string">&quot;\t&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println()</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Goland安装</title>
      <link href="golang/goland-install/"/>
      <url>golang/goland-install/</url>
      
        <content type="html"><![CDATA[<h1 id="⼀、安装Goland开发⼯具"><a href="#⼀、安装Goland开发⼯具" class="headerlink" title="⼀、安装Goland开发⼯具"></a>⼀、安装Goland开发⼯具</h1><h2 id="（⼀）、介绍"><a href="#（⼀）、介绍" class="headerlink" title="（⼀）、介绍"></a>（⼀）、介绍</h2><p>Goland是由JetBrains公司旨在为go开发者提供的⼀个符合⼈体⼯程学的新<br>的商业IDE。这个IDE整合了IntelliJ平台的有关go语⾔的编码辅助功能和⼯具集成<br>特点。它具有以下特点：</p><ul><li>编码辅助功能</li><li>符合⼈体⼯程学的设计</li><li>⼯具的集成</li><li>IntelliJ插件⽣态系统</li></ul><h2 id="（⼆）、下载及安装"><a href="#（⼆）、下载及安装" class="headerlink" title="（⼆）、下载及安装"></a>（⼆）、下载及安装</h2><p>1、官⽹下载地址：<a href="https://www.jetbrains.com/go/download/%E3%80%82%E4%B8%8B%E8%BD%BD%E5%AE%8C%E6%88%90%E5%90%8E%EF%BC%8C%E5%9C%A8">https://www.jetbrains.com/go/download/。下载完成后，在</a><br>本地执⾏解压，安装。</p><p>2、安装过程<br>点击“next”按钮，选择要安装的路径，然后点击“next”，会出现安装选项。<br>Goland安装和配置<br>根据你⾃⼰电脑的型号，选择合适的版本后点击“next”按钮。接着保持默认的程<br>序启动⽬录，点击“install”进⾏安装。整个安装过程很快，⼏乎⼀路next到底。</p><h2 id="（三）、使⽤Goland"><a href="#（三）、使⽤Goland" class="headerlink" title="（三）、使⽤Goland"></a>（三）、使⽤Goland</h2><p>1、打开Goland⼯具<br>2、创建项⽬：</p><h1 id="⼆、第⼀个程序：HelloWorld"><a href="#⼆、第⼀个程序：HelloWorld" class="headerlink" title="⼆、第⼀个程序：HelloWorld"></a>⼆、第⼀个程序：HelloWorld</h1><p>##（⼀）、编写第⼀个程序<br>1、打开编辑器创建⼀个新的helloworld.go⽂件，并输⼊以下内容：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"> <span class="comment">/* 输出 */</span></span><br><span class="line"> fmt.Println(<span class="string">&quot;Hello, World!&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>2、执⾏go程序<br>执⾏go程序由⼏种⽅式</p><p>⽅式⼀：使⽤go run命令</p><ul><li>step1：使⽤快捷键win+R，输⼊cmd打开命令⾏提示符</li><li>step2：进⼊helloworld.go所在的⽬录</li><li>step3：输⼊go run helloworld.go命令并观察运⾏结果。</li></ul><p>⽅式⼆：使⽤go build命令</p><ul><li>step1：使⽤快捷键win+R，输⼊cmd打开命令⾏提示符</li><li>step2：进⼊helloworld.go所在的⽬录</li><li>step3：输⼊go build helloworld.go命令进⾏编译，产⽣同名的<br>helloworld.exe⽂件</li><li>step4：输⼊helloworld.exe，执⾏</li></ul><p>⽅式三：使⽤ go playground</p><ul><li>step1：打开⼀下⽹址<a href="https://play.golang.org/">https://play.golang.org/</a></li></ul><h1 id="三、Goland常⽤快捷键"><a href="#三、Goland常⽤快捷键" class="headerlink" title="三、Goland常⽤快捷键"></a>三、Goland常⽤快捷键</h1><p>##（⼀）、⽂件相关快捷键：</p><ol><li>CTRL+E，打开最近浏览过的⽂件。</li><li>CTRL+SHIFT+E，打开最近更改的⽂件。</li><li>CTRL+N，可以快速打开struct结构体。</li><li>CTRL+SHIFT+N，可以快速打开⽂件。<br>##（⼆）、代码格式化：</li><li>CTRL+ALT+T，可以把代码包在⼀个块内，例如if{…}else{…}。</li><li>CTRL+ALT+L，格式化代码。</li><li>CTRL+空格，代码提示。</li><li>CTRL+/，单⾏注释。CTRL+SHIFT+/，进⾏多⾏注释。</li><li>CTRL+B，快速打开光标处的结构体或⽅法（跳转到定义处）。</li><li>CTRL+“+/-”，可以将当前⽅法进⾏展开或折叠。<br>##（三）、查找和定位</li><li>CTRL+R，替换⽂本。</li><li>CTRL+F，查找⽂本。</li><li>CTRL+SHIFT+F，进⾏全局查找。</li><li>CTRL+G，快速定位到某⾏。<h2 id="（四）、代码编辑"><a href="#（四）、代码编辑" class="headerlink" title="（四）、代码编辑"></a>（四）、代码编辑</h2></li><li>ALT+Q，可以看到当前⽅法的声明。</li><li>SHIFT+ENTER，可以向下插⼊新⾏，即使光标在当前⾏的中间。</li><li>CTRL+Backspace，按单词进⾏删除或删除光标所在⾏。</li><li>CTRL+X，剪切当前光标所在⾏。</li><li>CTRL+D，复制当前光标所在⾏。</li><li>ALT+SHIFT+UP/DOWN，可以将光标所在⾏的代码上下移动。</li><li>CTRL+SHIFT+U，可以将选中内容进⾏⼤⼩写转化。</li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
            <tag> Goland </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Golang课件索引</title>
      <link href="golang/golang-index/"/>
      <url>golang/golang-index/</url>
      
        <content type="html"><![CDATA[<h3 id="go学习pdf课件-大家可以收藏页面以免文件丢失"><a href="#go学习pdf课件-大家可以收藏页面以免文件丢失" class="headerlink" title="go学习pdf课件,大家可以收藏页面以免文件丢失"></a>go学习pdf课件,大家可以收藏页面以免文件丢失</h3><ul><li><a href="http://source.yufengming.com/golang/day04_00_Go%E8%AF%AD%E8%A8%80%E5%8F%91%E5%B1%95%E5%8E%86%E5%8F%B2%E3%80%81%E6%A0%B8%E5%BF%83%E7%89%B9%E6%80%A7%E5%8F%8A%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF.pdf">Go语言发展历史、核心特性及学习路线</a></li><li><a href="http://source.yufengming.com/golang/day04_01_Golang%E5%AE%89%E8%A3%85%E5%92%8C%E9%85%8D%E7%BD%AE.pdf">Golang安装和配置</a></li><li><a href="http://source.yufengming.com/golang/day04_02_Goland%E5%AE%89%E8%A3%85.pdf">Goland安装</a></li><li><a href="http://source.yufengming.com/golang/day04_03_HelloWorld%E7%A8%8B%E5%BA%8F%E8%A7%A3%E9%87%8A%E5%8F%8AGo%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83.pdf">HelloWorld程序解释及Go编码规范</a></li><li><a href="http://source.yufengming.com/golang/day04_04_Go%E8%AF%AD%E8%A8%80%E5%8F%98%E9%87%8F%E5%8F%8A%E5%B8%B8%E9%87%8F.pdf">Go语言变量及常量</a></li><li><a href="http://source.yufengming.com/golang/day04_05_Go%E8%AF%AD%E8%A8%80%E8%BF%90%E7%AE%97%E7%AC%A6.pdf">Go语言运算符</a></li><li><a href="http://source.yufengming.com/golang/day05_01_Go%E8%AF%AD%E8%A8%80%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6%E2%80%94%E2%80%94%E6%9D%A1%E4%BB%B6%E8%AF%AD%E5%8F%A5.pdf">Go语言流程控制——条件语句</a></li><li><a href="http://source.yufengming.com/golang/day05_02_Go%E8%AF%AD%E8%A8%80%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6%E2%80%94%E2%80%94%E5%BE%AA%E7%8E%AF%E8%AF%AD%E5%8F%A5.pdf">Go语言流程控制——循环语句</a></li><li><a href="http://source.yufengming.com/golang/day05_03_Go%E8%AF%AD%E8%A8%80%E5%87%BD%E6%95%B0%E4%B8%8E%E6%8C%87%E9%92%88.pdf">Go语言函数与指针</a></li><li><a href="http://source.yufengming.com/golang/day06_01_Go%E5%86%85%E7%BD%AE%E5%AE%B9%E5%99%A8_%E6%95%B0%E7%BB%84%E5%92%8C%E5%88%87%E7%89%87.pdf">Go内置容器_数组和切片</a></li><li><a href="http://source.yufengming.com/golang/day06_02_Go%E5%86%85%E7%BD%AE%E5%AE%B9%E5%99%A8_map%E4%B8%8Elist.pdf">Go内置容器_map与list</a></li><li><a href="http://source.yufengming.com/golang/day06_03_%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%A4%84%E7%90%86%E5%87%BD%E6%95%B0.pdf">字符串处理函数</a></li><li><a href="http://source.yufengming.com/golang/day06_04_time%E5%8F%8Amath%E5%8C%85%E5%8F%8A%E9%9A%8F%E6%9C%BA%E6%95%B0%E4%B8%8E%E9%94%AE%E7%9B%98%E8%BE%93%E5%85%A5.pdf">time及math包及随机数与键盘输入</a></li><li><a href="http://source.yufengming.com/golang/day06_05_regexp%E5%8C%85%E5%8F%8A%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E5%BA%94%E7%94%A8.pdf">regexp包及正则表达式的应用</a></li><li><a href="http://source.yufengming.com/golang/day07_01_OOP%E7%BC%96%E7%A8%8B.pdf">OOP编程</a></li><li><a href="http://source.yufengming.com/golang/day07_02_%E6%8E%A5%E5%8F%A3.pdf">接口</a></li><li><a href="http://source.yufengming.com/golang/day08_01_Go%E8%AF%AD%E8%A8%80%E7%9A%84%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C.pdf">Go语言的文件操作</a></li><li><a href="http://source.yufengming.com/golang/day08_02_Go%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86%E2%80%94%E2%80%94error.pdf">Go错误处理——error</a></li><li><a href="http://source.yufengming.com/golang/day08_03_Go%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E2%80%94%E2%80%94defer%E3%80%81panic%E3%80%81recover.pdf">Go异常处理——defer、panic、recover</a></li><li><a href="http://source.yufengming.com/golang/day09_01_%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E2%80%94%E2%80%94http.pdf">网络编程——http</a></li><li><a href="http://source.yufengming.com/golang/day09_02_HTTP%E7%8A%B6%E6%80%81%E7%A0%81.pdf">HTTP状态码</a></li><li><a href="http://source.yufengming.com/golang/day10_01_Go%E8%AF%AD%E8%A8%80%E6%95%B0%E6%8D%AE%E5%BA%93%E7%BC%96%E7%A8%8B.pdf">Go语言数据库编程</a></li><li><a href="http://source.yufengming.com/golang/day10_02_MySQL%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85%E6%AD%A5%E9%AA%A4.pdf">MySQL数据库安装步骤</a></li><li><a href="http://source.yufengming.com/golang/day11_MySQL%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B9%8BSQL%E9%AB%98%E7%BA%A7%E6%9F%A5%E8%AF%A2.pdf">MySQL数据库之SQL高级查询</a></li><li><a href="http://source.yufengming.com/golang/day12_%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8Bgoroutine.pdf">并发编程goroutine</a></li><li><a href="http://source.yufengming.com/golang/day13_%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8Bchannel.pdf">并发编程channel</a></li><li><a href="http://source.yufengming.com/golang/day14_01_Go%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95.pdf">Go加密算法</a></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> index </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Golang安装</title>
      <link href="golang/golang-install/"/>
      <url>golang/golang-install/</url>
      
        <content type="html"><![CDATA[<p>Golang安装和配置</p><h1 id="⼀、Golang安装"><a href="#⼀、Golang安装" class="headerlink" title="⼀、Golang安装"></a>⼀、Golang安装</h1><h2 id="（⼀）、下载"><a href="#（⼀）、下载" class="headerlink" title="（⼀）、下载"></a>（⼀）、下载</h2><p>在Mac、Windows和Linux三个平台上都⽀持Golang。您可以从<br><a href="https://golang.org/dl/%E4%B8%8B%E8%BD%BD%E7%9B%B8%E5%BA%94%E5%B9%B3%E5%8F%B0%E7%9A%84%E2%BC%86%E8%BF%9B%E5%88%B6%E2%BD%82%E4%BB%B6%E3%80%82%E8%AF%A5%E2%BD%B9%E7%AB%99%E5%9C%A8%E5%9B%BD%E5%86%85%E4%B8%8D%E5%AE%B9%E6%98%93%E8%AE%BF%E9%97%AE%EF%BC%8C">https://golang.org/dl/下载相应平台的⼆进制⽂件。该⽹站在国内不容易访问，</a><br>所以可以访问<a href="https://www.studygolang.com/dl">https://www.studygolang.com/dl</a> 进⾏安装软件的下载。</p><ul><li>Mac OS 从<a href="https://golang.org/dl/%E4%B8%8B%E8%BD%BDosx%E5%AE%89%E8%A3%85%E7%A8%8B%E5%BA%8F%E3%80%82%E5%8F%8C%E5%87%BB%E5%90%AF%E5%8A%A8%E5%AE%89%E8%A3%85%E3%80%82%E6%8C%89%E7%85%A7">https://golang.org/dl/下载osx安装程序。双击启动安装。按照</a><br>提示，这应该在/usr/local/go中安装了Golang，并且还会将⽂件<br>夹/usr/local/go/bin添加到您的PATH环境变量中。</li><li>Windows 从<a href="https://golang.org/dl/%E4%B8%8B%E8%BD%BDMSI%E5%AE%89%E8%A3%85%E7%A8%8B%E5%BA%8F%E3%80%82%E5%8F%8C%E5%87%BB%E5%90%AF%E5%8A%A8%E5%AE%89%E8%A3%85%E5%B9%B6%E9%81%B5">https://golang.org/dl/下载MSI安装程序。双击启动安装并遵</a><br>循提示。这将在位置c中安装Golang:\Go，并且还将添加⽬录c:\Go\bin到您<br>的path环境变量。</li><li>Linux 从<a href="https://golang.org/dl/%E4%B8%8B%E8%BD%BDtar%E2%BD%82%E4%BB%B6%EF%BC%8C%E5%B9%B6%E5%B0%86%E5%85%B6%E8%A7%A3%E5%8E%8B%E5%88%B0/usr/local%E3%80%82">https://golang.org/dl/下载tar⽂件，并将其解压到/usr/local。</a><br>将/usr/local/go/bin添加到PATH环境变量中。这应该安装在linux中。</li></ul><h1 id="⼆、-windows系统下安装和配置环境变量"><a href="#⼆、-windows系统下安装和配置环境变量" class="headerlink" title="⼆、 windows系统下安装和配置环境变量"></a>⼆、 windows系统下安装和配置环境变量</h1><h2 id="（⼀）、安装步骤⾮常简单，⼀路到底"><a href="#（⼀）、安装步骤⾮常简单，⼀路到底" class="headerlink" title="（⼀）、安装步骤⾮常简单，⼀路到底"></a>（⼀）、安装步骤⾮常简单，⼀路到底</h2><h2 id="（⼆）、配置环境变量"><a href="#（⼆）、配置环境变量" class="headerlink" title="（⼆）、配置环境变量"></a>（⼆）、配置环境变量</h2><h3 id="1、配置环境变量"><a href="#1、配置环境变量" class="headerlink" title="1、配置环境变量"></a>1、配置环境变量</h3><p>注意：如果是msi安装⽂件，Go语⾔的环境变量会⾃动设置好。<br>我的电脑——右键“属性”——“⾼级系统设置”——“环境变量”——“系统变量”<br>假设GO安装于C盘根⽬录<br>新建：</p><ul><li>GOROOT：Go安装路径（例：C:\Go）</li><li>GOPATH：Go⼯程的路径（例：E:\go）。如果有多个，就以分号分隔添<br>加</li></ul><p>修改：<br>Path：在path中增加：C:\Go\bin;%GOPATH%\bin;<br>需要把GOPATH中的可执⾏⽬录也配置到环境变量中, 否则你⾃⾏下载的第<br>三⽅go⼯具就⽆法使⽤了</p><ul><li>⼯作⽬录就是我们⽤来存放开发的源代码的地⽅，对应的也是Go⾥的<br>GOPATH这个环境变量。这个环境变量指定之后，我们编译源代码等⽣成的<br>⽂件都会放到这个⽬录下，GOPATH环境变量的配置参考上⾯的安装Go，配<br>置到Windows下的系统变量⾥。</li><li>GOPATH之下主要包含三个⽬录: bin、pkg、src。bin⽬录主要存放可执<br>⾏⽂件; pkg⽬录存放编译好的库⽂件, 主要是*.a⽂件; src⽬录下主要存放go<br>的源⽂件</li></ul><h3 id="2、查看是否安装配置成功"><a href="#2、查看是否安装配置成功" class="headerlink" title="2、查看是否安装配置成功"></a>2、查看是否安装配置成功</h3><p>使⽤快捷键win+R键，输⼊cmd，打开命令⾏提示符，在命令⾏中输⼊<br>go env # 查看得到go的配置信息<br>go version # 查看go的版本号</p><p>#三、mac系统安装并配置</p><h2 id="（⼀）、安装"><a href="#（⼀）、安装" class="headerlink" title="（⼀）、安装"></a>（⼀）、安装</h2><p>双击pkg包，顺着指引，即可安装成功。 在命令⾏输⼊ go version，获取到go的<br>版本号，则代表安装成功。</p><h2 id="（⼆）、配置环境变量-1"><a href="#（⼆）、配置环境变量-1" class="headerlink" title="（⼆）、配置环境变量"></a>（⼆）、配置环境变量</h2><ul><li>1、打开终端输⼊cd ~进⼊⽤户主⽬录;</li><li>2、输⼊ls -all命令查看是否存在.bash_profile;</li><li>3、存在既使⽤vim .bash_profile 打开⽂件;</li><li>4、输⼊ i 进⼊vim编辑模式；</li><li>5、输⼊下⾯代码， 其中 GOPATH: ⽇常开发的根⽬录。GOBIN:是GOPATH下的<br>bin⽬录。<br>export GOPATH=/Users/steven/Documents/go_project<br>export GOROOT= /Usr/local/go<br>export GOBIN=$GOROOT/bin<br>export PATH=$PATH:$GOBIN</li><li>6、点击ESC，并输⼊ :wq 保存并退出编辑。可输⼊vim .bash_profile 查看是否<br>保存成功。</li><li>7、输⼊source ~/.bash_profile 完成对golang环境变量的配置，配置成功没有提<br>示。</li><li>8、输⼊go env 查看配置结果</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Golang学习路线</title>
      <link href="golang/golang-study-route/"/>
      <url>golang/golang-study-route/</url>
      
        <content type="html"><![CDATA[<h1 id="⼀、第1章-初识Go语⾔"><a href="#⼀、第1章-初识Go语⾔" class="headerlink" title="⼀、第1章 初识Go语⾔"></a>⼀、第1章 初识Go语⾔</h1><ul><li>1 Go语⾔特性及发展过程、学习路线</li><li>2 安装Golang及设置环境变量+安装Goland开发环境</li><li>3 helloworld程序及go的程序结构<h1 id="⼆、第2章-Go基本语法"><a href="#⼆、第2章-Go基本语法" class="headerlink" title="⼆、第2章 Go基本语法"></a>⼆、第2章 Go基本语法</h1></li><li>1 变量、变量类型及注意事项</li><li>2 打印格式化介绍</li><li>3 常量与枚举</li><li>4 iota与常量注意事项</li><li>5 数据类型转换</li><li>6 表达式及运算符</li><li>7 键盘输⼊<h1 id="三、第3章-流程控制"><a href="#三、第3章-流程控制" class="headerlink" title="三、第3章 流程控制"></a>三、第3章 流程控制</h1></li><li>1 if条件语句</li><li>2 if嵌套</li><li>3 switch选择语句</li><li>4 跳转语句及fallthrough、break、continue的⽤法</li><li>5 for循环语句</li><li>6 for双层循环</li><li>7 随机数及随机数种⼦<h1 id="四、第4章-Go内置容器——数组及切⽚"><a href="#四、第4章-Go内置容器——数组及切⽚" class="headerlink" title="四、第4章 Go内置容器——数组及切⽚"></a>四、第4章 Go内置容器——数组及切⽚</h1></li><li>1 数组元素访问</li><li>2 ⼆维数组及多维数组</li><li>3 冒泡排序</li><li>4 切⽚slice的的概念</li><li>5 slice的操作<h1 id="五、第5章-Go内置容器——map字典"><a href="#五、第5章-Go内置容器——map字典" class="headerlink" title="五、第5章 Go内置容器——map字典"></a>五、第5章 Go内置容器——map字典</h1></li><li>1 map声明、创建和遍历</li><li>2 map元素删除、查找</li><li>3 map案例<h1 id="六、第6章-函数和指针"><a href="#六、第6章-函数和指针" class="headerlink" title="六、第6章 函数和指针"></a>六、第6章 函数和指针</h1></li><li>1 函数定义</li><li>2 函数调⽤</li><li>3 不定参数</li><li>4 函数多返回值</li><li>5 匿名函数和闭包</li><li>6 指针</li><li>7 深拷⻉和浅拷⻉<h1 id="七、第7章-Go⽂件操作"><a href="#七、第7章-Go⽂件操作" class="headerlink" title="七、第7章 Go⽂件操作"></a>七、第7章 Go⽂件操作</h1></li><li>1 内存存储</li><li>2 ⽂件存储<h1 id="⼋、第8章-错误处理"><a href="#⼋、第8章-错误处理" class="headerlink" title="⼋、第8章 错误处理"></a>⼋、第8章 错误处理</h1></li><li>1 error接⼝</li><li>2 defer语句</li><li>3 panic和recover<h1 id="九、第9章-Go单元测试"><a href="#九、第9章-Go单元测试" class="headerlink" title="九、第9章 Go单元测试"></a>九、第9章 Go单元测试</h1></li><li>1 Go进⾏单元测试</li><li>2 Go进⾏HTTP测试</li><li>3 第三⽅Go测试库（</li><li>4 Gocheck测试包</li><li>5 Ginkgo测试框架<h1 id="⼗、第10章-Go⾯向对象编程"><a href="#⼗、第10章-Go⾯向对象编程" class="headerlink" title="⼗、第10章 Go⾯向对象编程"></a>⼗、第10章 Go⾯向对象编程</h1></li><li>1 值类型和引⽤类型</li><li>2 结构体</li><li>3 ⽅法</li><li>4 接⼝</li><li>5 函数式编程<h1 id="⼗⼀、第11章-Go安全编程（加密处理）"><a href="#⼗⼀、第11章-Go安全编程（加密处理）" class="headerlink" title="⼗⼀、第11章 Go安全编程（加密处理）"></a>⼗⼀、第11章 Go安全编程（加密处理）</h1></li><li>1 哈希算法</li><li>2 数据加密</li><li>3 数字签名</li><li>4 数字证书</li><li>5 PKI体系</li><li>6 加密通信<h1 id="⼗⼆、第12章-Go并发编程"><a href="#⼗⼆、第12章-Go并发编程" class="headerlink" title="⼗⼆、第12章 Go并发编程"></a>⼗⼆、第12章 Go并发编程</h1></li><li>1 并发编程基础</li><li>2 多进程编程</li><li>3 多线程编程</li><li>4 Go的并发机制</li><li>5 协程及goroutine</li><li>6 channel</li><li>7 同步锁及原⼦操作<h1 id="⼗三、第13章-Go⽹络编程"><a href="#⼗三、第13章-Go⽹络编程" class="headerlink" title="⼗三、第13章 Go⽹络编程"></a>⼗三、第13章 Go⽹络编程</h1></li><li>1 Socket编程</li><li>2 HTTP编程</li><li>3 RPC编程（Gob及RPC接⼝）</li><li>4 JSON处理</li><li>5 ⽹站开发（net/http包）<h1 id="⼗四、第14章-Go数据库编程"><a href="#⼗四、第14章-Go数据库编程" class="headerlink" title="⼗四、第14章 Go数据库编程"></a>⼗四、第14章 Go数据库编程</h1></li><li>1 MySQL简介</li><li>2 MySQL noinstall安装</li><li>3 MySQL图形化⽅式安装</li><li>4 启动和停⽌MySQL服务</li><li>5 MySQL数据类型及客户端管理⼯具Navicat</li><li>6 SQL基础⼊⻔</li><li>7 SQL中运算符</li><li>8 SQL常⽤函数</li><li>9 DQL语句⾼级查询（模糊查询、内连接、外连接、⾃连接、⼦查询）</li><li>10 事务及回滚<h1 id="⼗五、第15章-Go爬⾍实战开发"><a href="#⼗五、第15章-Go爬⾍实战开发" class="headerlink" title="⼗五、第15章 Go爬⾍实战开发"></a>⼗五、第15章 Go爬⾍实战开发</h1></li><li>爬虫简介</li><li>爬虫原理</li><li>go中的爬虫库</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Golang学习笔记02</title>
      <link href="golang/golang-note2/"/>
      <url>golang/golang-note2/</url>
      
        <content type="html"><![CDATA[<p>变量: variable<br>概念: 一小块内存,用于存储数据,在程序运行过程中数值可以改变<br>使用:<br>    step1: 变量的声明,也叫定义<br>    step2: 变量的访问,赋值和取值<br>go的特性:<br>    静态语言:强类型语言<br>    go, Java, c++, c#<br>    动态语言:弱类型语言</p><h1 id="变量的定义"><a href="#变量的定义" class="headerlink" title="变量的定义"></a>变量的定义</h1><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 第一种:定义变量,然后进行赋值</span></span><br><span class="line"><span class="keyword">var</span> num1 <span class="keyword">int</span></span><br><span class="line">num1 = <span class="number">30</span></span><br><span class="line">fmt.Printf(<span class="string">&quot;num1d 数值是: %d\n&quot;</span>,num1)</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">在go中如果变量不被调用是不能运行成功的</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="comment">//  写在一行中</span></span><br><span class="line"><span class="keyword">var</span> num2 <span class="keyword">int</span> = <span class="number">15</span></span><br><span class="line">fmt.Printf(<span class="string">&quot;num2是:&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;%d\n&quot;</span>,num2)</span><br><span class="line"><span class="comment">/*第二种 类型的判断*/</span></span><br><span class="line"><span class="keyword">var</span> name = <span class="string">&quot;王二狗&quot;</span></span><br><span class="line">fmt.Printf(<span class="string">&quot;类型是:%T,namme是:&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;%s\n&quot;</span>,name,name)</span><br><span class="line"><span class="comment">// 第三种,剪短定义,也叫简短声明</span></span><br><span class="line">sum := <span class="number">100</span></span><br><span class="line">fmt.Println(sum)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 多个变量同时定义</span></span><br><span class="line"><span class="keyword">var</span> a,b,c <span class="keyword">int</span></span><br><span class="line">a = <span class="number">1</span></span><br><span class="line">b = <span class="number">2</span></span><br><span class="line">c = <span class="number">3</span></span><br><span class="line">fmt.Println(a,b,c)</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> m, n <span class="keyword">int</span> = <span class="number">100</span>, <span class="number">200</span></span><br><span class="line">fmt.Println(m,n)</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> n1,f1,s1 = <span class="number">100</span>,<span class="number">3.14</span>,<span class="string">&quot;GOGOGOG&quot;</span></span><br><span class="line">fmt.Println(n1,f1,s1)</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span>(</span><br><span class="line">studentName = <span class="string">&quot;李小花&quot;</span></span><br><span class="line">age = <span class="number">18</span></span><br><span class="line">sex = <span class="string">&quot;女&quot;</span></span><br><span class="line">)</span><br><span class="line">fmt.Println(<span class="string">&quot;学生姓名:%s, 年龄:%d,性别:%s\n&quot;</span>,studentName,age,sex)</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项:"></a>注意事项:</h2><ul><li>变量必须先定义才能使用</li><li>go语言是静态语言,要求变量的类型和赋值的类型必须一致</li><li>变量名不能冲突.*(同一个作用域内不能冲突)</li><li>简短定义方式,左边的变量名至少有一个是新的</li><li>剪短定义方式, 不能定义全局变量</li><li>变量的零值.也叫做默认值</li><li>变量定义了就要使用,否则无法通过编译</li></ul><p>如果在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明,<br>例如:</p><p>a := 20 </p><p>就是不被允许的,编译器会提示错误<br>no new variables on left side of :=</p><p>但是 a = 20 是可以的,因为这是给相同的变量赋予一个新的值.</p><p>如果你再定义变量a之前使用它,则会得到编译错误undefinded:a.<br>如果你声明了一个局部变量却没有在相同的代码块中使用他,同样会得到</p><h1 id="基本语法-常量"><a href="#基本语法-常量" class="headerlink" title="基本语法-常量"></a>基本语法-常量</h1><h2 id="常量的使用"><a href="#常量的使用" class="headerlink" title="常量的使用"></a>常量的使用</h2><h3 id="常量的声明"><a href="#常量的声明" class="headerlink" title="常量的声明"></a>常量的声明</h3><p>常量是一个简单值的标识符,在程序运行时,不会被修改的量.<br>const identifier [type] = value</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">显示类型定义: const b string &#x3D; &quot;abc</span><br><span class="line">隐示类型定义: const b &#x3D; &quot;abc</span><br></pre></td></tr></table></figure><h2 id="注意"><a href="#注意" class="headerlink" title="注意:"></a>注意:</h2><ul><li>在变量定义好后需要进行调用才行,而这里常量不需要<br>2020-02-25-golang-note2.md<h2 id="枚举类型"><a href="#枚举类型" class="headerlink" title="枚举类型"></a>枚举类型</h2>使用常量组作为枚举类型,一组相关数值的数据.</li></ul><hr><h1 id="go语言的数据类型"><a href="#go语言的数据类型" class="headerlink" title="go语言的数据类型"></a>go语言的数据类型</h1><h2 id="1-基本数据类型"><a href="#1-基本数据类型" class="headerlink" title="1. 基本数据类型"></a>1. 基本数据类型</h2><ul><li>布尔类型：bool<ul><li>取值：true</li><li>取值：false</li></ul></li><li>数值类型：<ul><li>整数：</li><li>浮点：生活中的小数</li><li>复数：complex，</li></ul></li><li>字符串：string<h2 id="2-复合数据类型"><a href="#2-复合数据类型" class="headerlink" title="2. 复合数据类型"></a>2. 复合数据类型</h2>array， slice， map， function， pointer， struct， interface， channel。。。</li></ul><ul><li><p>go语言出自名门正派,在go语言中可以看见C语言,Java甚至python的影子.</p></li><li><p>go通过协程(微线程)来实现更高性能的异步并发处理</p></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Golang学习笔记01</title>
      <link href="golang/golang-note1/"/>
      <url>golang/golang-note1/</url>
      
        <content type="html"><![CDATA[<h1 id="一、知名编程语⾔发展简史"><a href="#一、知名编程语⾔发展简史" class="headerlink" title="一、知名编程语⾔发展简史"></a>一、知名编程语⾔发展简史</h1><h2 id="（⼀）、知名编程语⾔或系统的发展简史"><a href="#（⼀）、知名编程语⾔或系统的发展简史" class="headerlink" title="（⼀）、知名编程语⾔或系统的发展简史"></a>（⼀）、知名编程语⾔或系统的发展简史</h2><h3 id="1、B语⾔之⽗"><a href="#1、B语⾔之⽗" class="headerlink" title="1、B语⾔之⽗"></a>1、B语⾔之⽗</h3><p>Ken Thompson（肯.汤普森）。该语⾔得名于汤姆森的妻⼦<br>Bonnie，⼀⻔剑桥于60年代中期开发的语⾔。</p><h3 id="2、C语⾔之⽗"><a href="#2、C语⾔之⽗" class="headerlink" title="2、C语⾔之⽗"></a>2、C语⾔之⽗</h3><p>美国著名计算机专家、C语⾔发明⼈、UNIX之⽗Dennis<br>Ritchie（丹尼斯·⾥奇）在1969-1973年期间发明了C语⾔和Unix操作系统。</p><h3 id="3、Unix之⽗"><a href="#3、Unix之⽗" class="headerlink" title="3、Unix之⽗"></a>3、Unix之⽗</h3><p>Dennis Ritchie（丹尼斯·⾥奇）及Ken Thompson（肯.汤普森）<br>在73年左右发明了Unix操作系统。两⼈因此获得1983年图灵奖。</p><h3 id="4、C-之⽗"><a href="#4、C-之⽗" class="headerlink" title="4、C++之⽗"></a>4、C++之⽗</h3><p>Bjarne Stroustrup（本贾尼·斯特劳斯特卢普）。1982年，美国<br>⻉尔实验室的Bjarne Stroustrup博⼠在C语⾔的基础上引⼊并扩充了⾯向对象的<br>概念，发明了—种新的程序语⾔。为了表达该语⾔与c语⾔的渊源关系，它被命<br>名为C++。</p><h3 id="5、Python之⽗"><a href="#5、Python之⽗" class="headerlink" title="5、Python之⽗"></a>5、Python之⽗</h3><p>Guido von Rossum（吉多.范.罗苏姆）。1989年，为了打发圣<br>诞节假期，Guido开始写Python语⾔的编译/解释器。1994年发布1.0版本。1995<br>年9⽉发布了Python3.5版。</p><h3 id="6、Java"><a href="#6、Java" class="headerlink" title="6、Java"></a>6、Java</h3><p>James Gosling（詹姆斯.⾼斯林）。1991年开发Oak，1994年更名为<br>Java。1995年5⽉正式发布。</p><h3 id="7、Javascript"><a href="#7、Javascript" class="headerlink" title="7、Javascript"></a>7、Javascript</h3><p>Brendan Eich（布兰登.艾奇)。艾奇对Java⼀点兴趣也没有，为<br>了应付公司安排的任务，他于1995年5⽉只⽤10天时间就把Javascript设计出来<br>了。</p><h3 id="8、Go语⾔"><a href="#8、Go语⾔" class="headerlink" title="8、Go语⾔"></a>8、Go语⾔</h3><p>Go的三个作者分别是：Robert Griesemer（罗伯特.格利茨默）,<br>Rob Pike（罗伯.派克） 和 Ken Thompson（肯.汤普森）。</p><ul><li>Robert在开发Go之前是Google V8、Chubby和HotSpot JVM的主要贡献<br>者；</li><li>Rob主要是Unix、UTF-8、plan9的作者；</li><li>Ken主要是B语⾔、C语⾔的作者、Unix之⽗。</li></ul><h2 id="⼆-、Go语⾔主要发展过程"><a href="#⼆-、Go语⾔主要发展过程" class="headerlink" title="(⼆)、Go语⾔主要发展过程"></a>(⼆)、Go语⾔主要发展过程</h2><p>1、2007年9⽉，Rob Pike（罗伯.派克） 正式命名为Go；<br>2、2008年5⽉，Google全⼒⽀持该项⽬；<br>3、2009年11⽉，Go将代码全部开源，它获得了当年的年度语⾔；<br>4、2012年3⽉28⽇，Go发布第⼀个正式的稳定版本。  </p><ul><li>Go稳定版发布时，Go Team承诺后续的版本都会兼容之前的版本。这对<br>于开发者来说⾮常重要，Go后续的版本也⼀直在提升内功，从⽽可以让⽤<br>户⽆缝的升级Go版本。</li></ul><h1 id="⼆、Go语⾔的特点及优势"><a href="#⼆、Go语⾔的特点及优势" class="headerlink" title="⼆、Go语⾔的特点及优势"></a>⼆、Go语⾔的特点及优势</h1><h2 id="（⼀）、Go语⾔设计初衷（为什么会设计Go语⾔？）"><a href="#（⼀）、Go语⾔设计初衷（为什么会设计Go语⾔？）" class="headerlink" title="（⼀）、Go语⾔设计初衷（为什么会设计Go语⾔？）"></a>（⼀）、Go语⾔设计初衷（为什么会设计Go语⾔？）</h2><h3 id="1、设计Go语⾔是为了解决当时Google开发遇到的问题"><a href="#1、设计Go语⾔是为了解决当时Google开发遇到的问题" class="headerlink" title="1、设计Go语⾔是为了解决当时Google开发遇到的问题"></a>1、设计Go语⾔是为了解决当时Google开发遇到的问题</h3><ul><li>⼤量的C++代码，同时⼜引⼊了Java和Python</li><li>成千上万的⼯程师</li><li>数以万计⾏的代码</li><li>分布式的编译系统</li><li>数百万的服务器<h3 id="2、Google开发中的痛点"><a href="#2、Google开发中的痛点" class="headerlink" title="2、Google开发中的痛点"></a>2、Google开发中的痛点</h3></li><li>编译慢</li><li>失控的依赖</li><li>每个⼯程师只是⽤了⼀个语⾔⾥⾯的⼀部分</li><li>程序难以维护（可读性差、⽂档不清晰等）</li><li>更新的花费越来越⻓</li><li>交叉编译困难</li></ul><h3 id="3、如何解决当前的问题和痛点？"><a href="#3、如何解决当前的问题和痛点？" class="headerlink" title="3、如何解决当前的问题和痛点？"></a>3、如何解决当前的问题和痛点？</h3><ul><li>Go希望成为互联⽹时代的C语⾔。多数系统级语⾔（包括Java和C#）的<br>根本编程哲学来源于C++，将C++的⾯向对象进⼀步发扬光⼤。但是Go语⾔<br>的设计者却有不同的看法，他们认为值得学习的是C语⾔。C语⾔经久不衰<br>的根源是它⾜够简单。因此，Go语⾔也是⾜够简单。</li><li>所以，他们当时设计Go的⽬标是为了消除各种缓慢和笨重、改进各种低<br>效和扩展性。Go是由那些开发⼤型系统的⼈设计的，同时也是为了这些⼈<br>服务的；它是为了解决⼯程上的问题，不是为了研究语⾔设计；它还是为了<br>让我们的编程变得更舒适和⽅便。</li><li>但是结合Google当时内部的⼀些现实情况，如很多⼯程师都是C系的，所<br>以新设计的语⾔⼀定要易学习，最好是类似C的语⾔；20年没有出新的语⾔<br>了，所以新设计的语⾔必须是现代化的（例如内置GC）等情况。最后根据<br>实战经验，他们向着⽬标设计了Go这个语⾔。<h3 id="4、Go语⾔的特⾊："><a href="#4、Go语⾔的特⾊：" class="headerlink" title="4、Go语⾔的特⾊："></a>4、Go语⾔的特⾊：</h3></li><li>没有继承多态的⾯向对象</li><li>强⼀致类型</li><li>interface不需要显式声明(Duck Typing)</li><li>没有异常处理(Error is value)</li><li>基于⾸字⺟的可访问特性</li><li>不⽤的import或者变量引起编译错误</li><li>完整⽽卓越的标准库包</li><li>Go内置runtime（作⽤是性能监控、垃圾回收等）</li></ul><h2 id="（⼆）、Go语⾔的优势"><a href="#（⼆）、Go语⾔的优势" class="headerlink" title="（⼆）、Go语⾔的优势"></a>（⼆）、Go语⾔的优势</h2><h3 id="1、学习曲线容易"><a href="#1、学习曲线容易" class="headerlink" title="1、学习曲线容易"></a>1、学习曲线容易</h3><p>Go语⾔语法简单，包含了类C语法。因为Go语⾔容易学习，所以⼀个普通<br>的⼤学⽣花⼏个星期就能写出来可以上⼿的、⾼性能的应⽤。在国内⼤家都追求<br>快，这也是为什么国内Go流⾏的原因之⼀。</p><h3 id="2、效率：快速的编译时间，开发效率和运⾏效率⾼"><a href="#2、效率：快速的编译时间，开发效率和运⾏效率⾼" class="headerlink" title="2、效率：快速的编译时间，开发效率和运⾏效率⾼"></a>2、效率：快速的编译时间，开发效率和运⾏效率⾼</h3><p>开发过程中相较于 Java 和 C++呆滞的编译速度，Go 的快速编译时间是⼀<br>个主要的效率优势。Go拥有接近C的运⾏效率和接近PHP的开发效率。</p><h3 id="3、出身名⻔、⾎统纯正"><a href="#3、出身名⻔、⾎统纯正" class="headerlink" title="3、出身名⻔、⾎统纯正"></a>3、出身名⻔、⾎统纯正</h3><p>之所以说Go出身名⻔，从Go语⾔的创造者就可⻅端倪，Go语⾔绝对⾎统纯<br>正。其次Go语⾔出⾃Google公司，Google在业界的知名度和实⼒⾃然不⽤多<br>说。Google公司聚集了⼀批⽜⼈，在各种编程语⾔称雄争霸的局⾯下推出新的<br>编程语⾔，⾃然有它的战略考虑。⽽且从Go语⾔的发展态势来看，Google对它<br>这个新的宠⼉还是很看重的，Go⾃然有⼀个良好的发展前途。</p><h3 id="4、⾃由⾼效：组合的思想、⽆侵⼊式的接⼝"><a href="#4、⾃由⾼效：组合的思想、⽆侵⼊式的接⼝" class="headerlink" title="4、⾃由⾼效：组合的思想、⽆侵⼊式的接⼝"></a>4、⾃由⾼效：组合的思想、⽆侵⼊式的接⼝</h3><p>Go语⾔可以说是开发效率和运⾏效率⼆者的完美融合，天⽣的并发编程⽀<br>持。Go语⾔⽀持当前所有的编程范式，包括过程式编程、⾯向对象编程、⾯向<br>接⼝编程、函数式编程。程序员们可以各取所需、⾃由组合、想怎么玩就怎么<br>玩。</p><h3 id="5、强⼤的标准库"><a href="#5、强⼤的标准库" class="headerlink" title="5、强⼤的标准库"></a>5、强⼤的标准库</h3><p>这包括互联⽹应⽤、系统编程和⽹络编程。Go⾥⾯的标准库基本上已经是<br>⾮常稳定了，特别是我这⾥提到的三个，⽹络层、系统层的库⾮常实⽤。</p><h3 id="6、部署⽅便：⼆进制⽂件，Copy部署"><a href="#6、部署⽅便：⼆进制⽂件，Copy部署" class="headerlink" title="6、部署⽅便：⼆进制⽂件，Copy部署"></a>6、部署⽅便：⼆进制⽂件，Copy部署</h3><p>这⼀点是很多⼈选择Go的最⼤理由，因为部署太⽅便了，所以现在也有很<br>多⼈⽤Go开发运维程序。</p><h3 id="7、简单的并发"><a href="#7、简单的并发" class="headerlink" title="7、简单的并发"></a>7、简单的并发</h3><ul><li>Go 是⼀种⾮常⾼效的语⾔，⾼度⽀持并发性。Go是为⼤数据、微服务、并<br>发⽽⽣的⼀种编程语⾔。</li><li>Go 作为⼀⻔语⾔致⼒于使事情简单化。它并未引⼊很多新概念，⽽是聚<br>焦于打造⼀⻔简单的语⾔，它使⽤起来异常快速并且简单。其唯⼀的创新之<br>处是 goroutines 和通道。Goroutines 是 Go ⾯向线程的轻量级⽅法，⽽通<br>道是 goroutines 之间通信的优先⽅式。</li><li>创建 Goroutines 的成本很低，只需⼏千个字节的额外内存，正由于此，<br>才使得同时运⾏数百个甚⾄数千个 goroutines 成为可能。可以借助通道实<br>现 goroutines 之间的通信。Goroutines 以及基于通道的并发性⽅法使其⾮<br>常容易使⽤所有可⽤的 CPU 内核，并处理并发的 IO。相较于<br>Python/Java，在⼀个 goroutine 上运⾏⼀个函数需要最⼩的代码。<h3 id="8、稳定性"><a href="#8、稳定性" class="headerlink" title="8、稳定性"></a>8、稳定性</h3>Go拥有强⼤的编译检查、严格的编码规范和完整的软件⽣命周期⼯具，具有很强的稳定性，稳定压倒⼀切。那么为什么Go相⽐于其他程序会更稳定呢？<br>这是因为Go提供了软件⽣命周期（开发、测试、部署、维护等等）的各个环节<br>的⼯具，如go tool、gofmt、go test。<h2 id="（三）、Go语⾔的核⼼特性和优势"><a href="#（三）、Go语⾔的核⼼特性和优势" class="headerlink" title="（三）、Go语⾔的核⼼特性和优势"></a>（三）、Go语⾔的核⼼特性和优势</h2></li><li>Go主要有静态语⾔、函数多返回值、天⽣并发、内置GC（⾃动垃圾回<br>收）、安全性⾼、语法简单、编译快速这⼏个⽅⾯的特性。这些特性决定了<br>Go的三个⾼富帅特性：运⾏快、开发快和部署快。<ul><li>静态类型语⾔是指在编译时变量的数据类型即可确定的语⾔，要求在使⽤变量之前必须声明数据类型（具有类型推导能⼒的现代语⾔可能能够部分减轻这个要求）；</li><li>动态类型语⾔是在运⾏时确定数据类型的语⾔，变量使⽤之前不需要类型声明，通常变量的类型是被赋值的那个值的类型。</li></ul></li><li>Go语⾔是⽬前项⽬转型⾸选的语⾔，也是软件⼯程师转型⾸选的语⾔，<br>是添加技术栈的⾸选语⾔。Go常常是⼀种为转型⽽量身定制的语⾔。<h2 id="（四）、Go语⾔能开发什么？"><a href="#（四）、Go语⾔能开发什么？" class="headerlink" title="（四）、Go语⾔能开发什么？"></a>（四）、Go语⾔能开发什么？</h2></li><li>1、服务器编程<br>以前你如果使⽤C或者C++做的那些事情，⽤Go来做很合适，<br>例如处理⽇志、数据打包、虚拟机处理、⽂件系统等。</li><li>2、分布式系统、数据库代理器、中间件等，例如Etcd。</li><li>3、⽹络编程，这⼀块⽬前应⽤最⼴，包括Web应⽤、API应⽤、下载应⽤，⽽且Go内置的net/http包基本上把我们平常⽤到的⽹络功能都实现了。</li><li>4、数据库操作</li><li>5、开发云平台，⽬前国外很多云平台在采⽤Go开发<h2 id="（五）、采⽤Go语⾔的国内外知名企业"><a href="#（五）、采⽤Go语⾔的国内外知名企业" class="headerlink" title="（五）、采⽤Go语⾔的国内外知名企业"></a>（五）、采⽤Go语⾔的国内外知名企业</h2></li><li>1、Go发布之后，很多公司特别是云计算公司开始⽤Go重构他们的基础架构，很<br>多都是直接采⽤Go进⾏了开发，最近热⽕朝天的Docker就是采⽤Go开发的；</li><li>2、采⽤Go的⼀些国外公司，如Google、Docker、Apple、Cloud Foundry、<br>CloudFlare、Couchbase、CoreOS、Dropbox、MongoDB、AWS等公司；</li><li>3、采⽤Go开发的国内企业：如阿⾥云CDN、百度、⼩⽶、七⽜、PingCAP、华<br>为、⾦⼭软件、猎豹移动、饿了么等公司。</li></ul><h1 id="参考相关源"><a href="#参考相关源" class="headerlink" title="参考相关源"></a>参考相关源</h1><p><a href="https://www.runoob.com/go/go-environment.html">Golang菜鸟教程</a></p><p><a href="http://c.biancheng.net/golang/">Go语言入门教程-C语言中文网</a></p><p><a href="https://studygolang.com/dl">Go语言中文网</a></p><h1 id="下载安装"><a href="#下载安装" class="headerlink" title="下载安装"></a>下载安装</h1><p>由于官方网站需要翻墙,所有我们在国内可以去<br><a href="https://studygolang.com/dl">Go语言中文网</a>中进行下载安装</p><p>其中提供多种操作系统环境的安装,安装形式分为压缩版和安装包版本</p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Golang </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中的faker</title>
      <link href="python/collection/python-faker/"/>
      <url>python/collection/python-faker/</url>
      
        <content type="html"><![CDATA[<h2 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h2><p>faker (伪装者)创建假数据<br>工作中，有时候我们需要伪造一些假数据，如何使用 Python 伪造这些看起来一点也不假的假数据呢？<br>Python 有一个包叫 Faker，使用它可以轻易地伪造姓名、地址、手机号等等信息。</p><h2 id="1-安装faker包"><a href="#1-安装faker包" class="headerlink" title="1.安装faker包"></a>1.安装faker包</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install faker</span><br></pre></td></tr></table></figure><h2 id="2-安装完成后"><a href="#2-安装完成后" class="headerlink" title="2.安装完成后"></a>2.安装完成后</h2><p>使用时需要先创建一个 Faker 对象，创建方法有两种，一种是直接通过构造函数来创建，另一种是通过工厂函数来创建。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; from faker import Faker, Factory</span><br><span class="line">&gt;&gt;&gt; fake1 &#x3D; Factory.create() # 通过工厂函数来创建</span><br><span class="line">&gt;&gt;&gt; fake1.name() # 随机生成一个姓名</span><br><span class="line">&#39;Austin Parker&#39;</span><br><span class="line">&gt;&gt;&gt; fake2 &#x3D; Faker() # 通过构造函数来创建</span><br><span class="line">&gt;&gt;&gt; fake2.name() # 随机生成一个姓名</span><br><span class="line">&#39;Linda Castaneda&#39;</span><br></pre></td></tr></table></figure><h2 id="3-各种数据项"><a href="#3-各种数据项" class="headerlink" title="3.各种数据项"></a>3.各种数据项</h2><h3 id="3-1中国人名"><a href="#3-1中国人名" class="headerlink" title="3.1中国人名"></a>3.1中国人名</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake &#x3D; Faker(&quot;zh_CN&quot;)</span><br><span class="line">&gt;&gt;&gt; fake.name()</span><br><span class="line">&#39;西建平&#39;</span><br></pre></td></tr></table></figure><h3 id="3-2地址"><a href="#3-2地址" class="headerlink" title="3.2地址"></a>3.2地址</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.city() # 城市名称</span><br><span class="line">&#39;辛集县&#39;</span><br><span class="line">&gt;&gt;&gt; fake.street_name() # 街道名称</span><br><span class="line">&#39;荆街&#39;</span><br><span class="line">&gt;&gt;&gt; fake.country_code() # 国家编号</span><br><span class="line">&#39;DM&#39;</span><br><span class="line">&gt;&gt;&gt; fake.longitude() # 经度</span><br><span class="line">Decimal(&#39;134.520688&#39;)</span><br><span class="line">&gt;&gt;&gt; fake.address() # 地址</span><br><span class="line">&#39;吉林省宜都市清河俞街j座 292426&#39;</span><br><span class="line">&gt;&gt;&gt; fake.province() # 省份</span><br><span class="line">&#39;宁夏回族自治区&#39;</span><br><span class="line">&gt;&gt;&gt; fake.latitude() # 纬度</span><br><span class="line">Decimal(&#39;-14.386640&#39;)</span><br><span class="line">&gt;&gt;&gt; fake.street_address() # 街道地址</span><br><span class="line">&#39;益路v座&#39;</span><br><span class="line">&gt;&gt;&gt; fake.city_suffix() # 市</span><br><span class="line">&#39;市&#39;</span><br><span class="line">&gt;&gt;&gt; fake.postcode() # 邮政编码</span><br><span class="line">&#39;530435&#39;</span><br><span class="line">&gt;&gt;&gt; fake.country() # 国家</span><br><span class="line">&#39;维尔京群岛&#39;</span><br><span class="line">&gt;&gt;&gt; fake.street_suffix() # 街道后缀</span><br><span class="line">&#39;街&#39;</span><br><span class="line">&gt;&gt;&gt; fake.district() # 区</span><br><span class="line">&#39;安次&#39;</span><br><span class="line">&gt;&gt;&gt; fake.geo_coordinate(center&#x3D;None, radius&#x3D;0.001) # 地理坐标</span><br><span class="line">Decimal(&#39;52.985293&#39;)</span><br><span class="line">&gt;&gt;&gt; fake.city_name() # 城市名称</span><br><span class="line">&#39;沈阳&#39;</span><br><span class="line">&gt;&gt;&gt; fake.building_number() # 建筑编号</span><br><span class="line">&#39;C座&#39;</span><br></pre></td></tr></table></figure><h3 id="3-3车牌号"><a href="#3-3车牌号" class="headerlink" title="3.3车牌号"></a>3.3车牌号</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.license_plate() # 车牌号</span><br><span class="line">&#39;26FX4&#39;</span><br></pre></td></tr></table></figure><h2 id="4-条形码"><a href="#4-条形码" class="headerlink" title="4.条形码"></a>4.条形码</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.bank_country()</span><br><span class="line">&#39;GB&#39;</span><br><span class="line">&gt;&gt;&gt; fake.iban()</span><br><span class="line">&#39;GB39SNOA2073712937476&#39;</span><br><span class="line">&gt;&gt;&gt; fake.bban()</span><br><span class="line">&#39;NYJX570813729289</span><br></pre></td></tr></table></figure><h2 id="5-颜色"><a href="#5-颜色" class="headerlink" title="5.颜色"></a>5.颜色</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.color_name() # 颜色名称</span><br><span class="line">&#39;SlateGray&#39;</span><br><span class="line">&gt;&gt;&gt; fake.safe_hex_color() # safe 颜色 16 进制编号</span><br><span class="line">&#39;#111100&#39;</span><br><span class="line">&gt;&gt;&gt; fake.safe_color_name() # safe颜色名称</span><br><span class="line">&#39;black&#39;</span><br><span class="line">&gt;&gt;&gt; fake.rgb_color() # 颜色的 rgb 值</span><br><span class="line">&#39;46,180,218&#39;</span><br><span class="line">&gt;&gt;&gt; fake.hex_color() # 颜色 16 进制编号</span><br><span class="line">&#39;#81b632&#39;</span><br><span class="line">&gt;&gt;&gt; fake.rgb_css_color()</span><br><span class="line">&#39;rgb(27,224,190)&#39;</span><br></pre></td></tr></table></figure><h2 id="6-公司"><a href="#6-公司" class="headerlink" title="6.公司"></a>6.公司</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.catch_phrase()</span><br><span class="line">&#39;Persistent bandwidth-monitored system engine&#39;</span><br><span class="line">&gt;&gt;&gt; fake.company_prefix() # 公司名前缀</span><br><span class="line">&#39;联通时科&#39;</span><br><span class="line">&gt;&gt;&gt; fake.company() # 公司名</span><br><span class="line">&#39;方正科技信息有限公司&#39;</span><br><span class="line">&gt;&gt;&gt; fake.company_suffix() # 公司名后缀</span><br><span class="line">&#39;信息有限公司&#39;</span><br><span class="line">&gt;&gt;&gt; fake.bs()</span><br><span class="line">&#39;transition revolutionary action-items&#39;</span><br></pre></td></tr></table></figure><h2 id="7-信用卡"><a href="#7-信用卡" class="headerlink" title="7.信用卡"></a>7.信用卡</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.credit_card_full(card_type&#x3D;None) # 完整卡信息</span><br><span class="line">&#39;JCB 15 digit\n秀梅 段\n180053229428785 07&#x2F;21\nCVC: 628\n&#39;</span><br><span class="line">&gt;&gt;&gt; fake.credit_card_provider(card_type&#x3D;None) # 卡的提供者</span><br><span class="line">&#39;VISA 16 digit&#39;</span><br><span class="line">&gt;&gt;&gt; fake.credit_card_expire(start&#x3D;&quot;now&quot;, end&#x3D;&quot;+10y&quot;, date_format&#x3D;&quot;%m&#x2F;%y&quot;) # 卡的有效期</span><br><span class="line">&#39;06&#x2F;19&#39;</span><br><span class="line">&gt;&gt;&gt; fake.credit_card_number(card_type&#x3D;None) # 卡号</span><br><span class="line">&#39;4946562273912&#39;</span><br><span class="line">&gt;&gt;&gt; fake.credit_card_security_code(card_type&#x3D;None) # 卡的安全密码</span><br><span class="line">&#39;985&#39;</span><br></pre></td></tr></table></figure><h2 id="8-货币"><a href="#8-货币" class="headerlink" title="8.货币"></a>8.货币</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.cryptocurrency()</span><br><span class="line">(&#39;BTC&#39;, &#39;Bitcoin&#39;)</span><br><span class="line">&gt;&gt;&gt; fake.cryptocurrency_code()</span><br><span class="line">&#39;USDT&#39;</span><br><span class="line">&gt;&gt;&gt; fake.currency_code()</span><br><span class="line">&#39;SZL&#39;</span><br><span class="line">&gt;&gt;&gt; fake.currency_name()</span><br><span class="line">&#39;Dominican peso&#39;</span><br><span class="line">&gt;&gt;&gt; fake.currency()</span><br><span class="line">(&#39;ZWD&#39;, &#39;Zimbabwean dollar&#39;)</span><br><span class="line">&gt;&gt;&gt; fake.cryptocurrency_name()</span><br><span class="line">&#39;Cardano&#39;</span><br></pre></td></tr></table></figure><h2 id="9-时间日期"><a href="#9-时间日期" class="headerlink" title="9.时间日期"></a>9.时间日期</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.date_time(tzinfo&#x3D;None) # 随机日期时间</span><br><span class="line">datetime.datetime(2001, 3, 18, 17, 57, 44)</span><br><span class="line">&gt;&gt;&gt; fake.iso8601(tzinfo&#x3D;None) # 以iso8601标准输出的日期</span><br><span class="line">&#39;1973-11-16T22:58:37&#39;</span><br><span class="line">&gt;&gt;&gt; fake.date_time_this_month(before_now&#x3D;True, after_now&#x3D;False, tzinfo&#x3D;None) # 本月的某个日期</span><br><span class="line">datetime.datetime(2017, 11, 1, 14, 33, 48)</span><br><span class="line">&gt;&gt;&gt; fake.date_time_this_year(before_now&#x3D;True, after_now&#x3D;False, tzinfo&#x3D;None) # 本年的某个日期</span><br><span class="line">datetime.datetime(2017, 3, 2, 13, 55, 31)</span><br><span class="line">&gt;&gt;&gt; fake.date_time_this_decade(before_now&#x3D;True, after_now&#x3D;False, tzinfo&#x3D;None)  # 本年代内的一个日期</span><br><span class="line">datetime.datetime(2010, 3, 26, 6, 33, 23)</span><br><span class="line">&gt;&gt;&gt; fake.date_time_this_century(before_now&#x3D;True, after_now&#x3D;False, tzinfo&#x3D;None)  # 本世纪一个日期</span><br><span class="line">datetime.datetime(2015, 7, 21, 19, 27, 53)</span><br><span class="line">&gt;&gt;&gt; fake.date_time_between(start_date&#x3D;&quot;-30y&quot;, end_date&#x3D;&quot;now&quot;, tzinfo&#x3D;None)  # 两个时间间的一个随机时间</span><br><span class="line">datetime.datetime(2005, 12, 3, 17, 17, 15)</span><br><span class="line">&gt;&gt;&gt; fake.timezone() # 时区</span><br><span class="line">&#39;America&#x2F;Guatemala&#39;</span><br><span class="line">&gt;&gt;&gt; fake.time(pattern&#x3D;&quot;%H:%M:%S&quot;) # 时间（可自定义格式）</span><br><span class="line">&#39;11:21:52&#39;</span><br><span class="line">&gt;&gt;&gt; fake.am_pm() # 随机上午下午</span><br><span class="line">&#39;PM&#39;</span><br><span class="line">&gt;&gt;&gt; fake.month() # 随机月份</span><br><span class="line">&#39;02&#39;</span><br><span class="line">&gt;&gt;&gt; fake.month_name() # 随机月份名字</span><br><span class="line">&#39;August&#39;</span><br><span class="line">&gt;&gt;&gt; fake.year() # 随机年</span><br><span class="line">&#39;1974&#39;</span><br><span class="line">&gt;&gt;&gt; fake.day_of_week() # 随机星期几</span><br><span class="line">&#39;Sunday&#39;</span><br><span class="line">&gt;&gt;&gt; fake.day_of_month() # 随机月中某一天</span><br><span class="line">&#39;02&#39;</span><br><span class="line">&gt;&gt;&gt; fake.time_delta() # 随机时间延迟</span><br><span class="line">datetime.timedelta(13371, 27637)</span><br><span class="line">&gt;&gt;&gt; fake.date_object()  # 随机日期对象</span><br><span class="line">datetime.date(1983, 1, 26)</span><br><span class="line">&gt;&gt;&gt; fake.time_object() # 随机时间对象</span><br><span class="line">datetime.time(17, 8, 56)</span><br><span class="line">&gt;&gt;&gt; fake.unix_time() # 随机unix时间（时间戳）</span><br><span class="line">1223246848</span><br><span class="line">&gt;&gt;&gt; fake.date(pattern&#x3D;&quot;%Y-%m-%d&quot;) # 随机日期（可自定义格式）</span><br><span class="line">&#39;1984-04-20&#39;</span><br><span class="line">&gt;&gt;&gt; fake.date_time_ad(tzinfo&#x3D;None)  # 公元后随机日期</span><br><span class="line">datetime.datetime(341, 9, 11, 8, 6, 9)</span><br></pre></td></tr></table></figure><h2 id="10-工作"><a href="#10-工作" class="headerlink" title="10.工作"></a>10.工作</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.job()</span><br><span class="line">&#39;Development worker, community&#39;</span><br></pre></td></tr></table></figure><h2 id="11-文件"><a href="#11-文件" class="headerlink" title="11.文件"></a>11.文件</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.unix_partition(prefix&#x3D;None) # unix 分区</span><br><span class="line">&#39;&#x2F;dev&#x2F;sdg5&#39;</span><br><span class="line">&gt;&gt;&gt; fake.file_name(category&#x3D;None, extension&#x3D;None) # 文件名</span><br><span class="line">&#39;看到.flac&#39;</span><br><span class="line">&gt;&gt;&gt; fake.unix_device(prefix&#x3D;None) # unix 设备</span><br><span class="line">&#39;&#x2F;dev&#x2F;vdu&#39;</span><br><span class="line">&gt;&gt;&gt; fake.file_path(depth&#x3D;1, category&#x3D;None, extension&#x3D;None)</span><br><span class="line">&#39;&#x2F;合作&#x2F;国家.webm&#39;</span><br><span class="line">&gt;&gt;&gt; fake.file_extension(category&#x3D;None) # 文件扩展信息</span><br><span class="line">&#39;mp3&#39;</span><br><span class="line">&gt;&gt;&gt; fake.mime_type(category&#x3D;None)</span><br><span class="line">&#39;text&#x2F;csv&#39;</span><br></pre></td></tr></table></figure><h2 id="12-互联网"><a href="#12-互联网" class="headerlink" title="12.互联网"></a>12.互联网</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.ipv4(network&#x3D;False)  # ipv4地址</span><br><span class="line">&#39;104.225.105.10&#39;</span><br><span class="line">&gt;&gt;&gt; fake.ipv6(network&#x3D;False)  # ipv6地址</span><br><span class="line">&#39;dea6:ca11:39d0:b49f:fff1:82f1:bf88:698b&#39;</span><br><span class="line">&gt;&gt;&gt; fake.uri_path(deep&#x3D;None) # uri路径</span><br><span class="line">&#39;search&#x2F;categories&#39;</span><br><span class="line">&gt;&gt;&gt; fake.uri_extension() # uri扩展名</span><br><span class="line">&#39;.htm&#39;</span><br><span class="line">&gt;&gt;&gt; fake.uri() # uri</span><br><span class="line">&#39;https:&#x2F;&#x2F;www.wei.com&#x2F;terms&#x2F;&#39;</span><br><span class="line">&gt;&gt;&gt; fake.url() # url</span><br><span class="line">&#39;http:&#x2F;&#x2F;zheng.org&#x2F;&#39;</span><br><span class="line">&gt;&gt;&gt; fake.image_url(width&#x3D;None, height&#x3D;None)  # 图片url</span><br><span class="line">&#39;https:&#x2F;&#x2F;www.lorempixel.com&#x2F;700&#x2F;990&#39;</span><br><span class="line">&gt;&gt;&gt; fake.domain_word() # 域名主体</span><br><span class="line">&#39;hu&#39;</span><br><span class="line">&gt;&gt;&gt; fake.domain_name() # 域名</span><br><span class="line">&#39;hu.cn&#39;</span><br><span class="line">&gt;&gt;&gt; fake.tld() # 域名后缀</span><br><span class="line">&#39;com&#39;</span><br><span class="line">&gt;&gt;&gt; fake.user_name() # 用户名</span><br><span class="line">&#39;xia13&#39;</span><br><span class="line">&gt;&gt;&gt; fake.user_agent() # UA</span><br><span class="line">&#39;Opera&#x2F;8.33.(Windows NT 5.1; an-ES) Presto&#x2F;2.9.171 Version&#x2F;10.00&#39;</span><br><span class="line">&gt;&gt;&gt; fake.mac_address() # MAC地址</span><br><span class="line">&#39;d6:38:cc:2a:76:b2&#39;</span><br><span class="line">&gt;&gt;&gt; fake.safe_email() # 安全邮箱</span><br><span class="line">&#39;mingli@example.net&#39;</span><br><span class="line">&gt;&gt;&gt; fake.free_email() # 免费邮箱</span><br><span class="line">&#39;tao44@gmail.com&#39;</span><br><span class="line">&gt;&gt;&gt; fake.company_email()  # 公司邮箱</span><br><span class="line">&#39;jingzhong@wang.cn&#39;</span><br><span class="line">&gt;&gt;&gt; fake.email() # 邮箱</span><br><span class="line">&#39;changjun@hao.com&#39;</span><br></pre></td></tr></table></figure><h2 id="13-电话号码"><a href="#13-电话号码" class="headerlink" title="13.电话号码"></a>13.电话号码</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.phonenumber_prefix() # 运营商号段，手机号前三位</span><br><span class="line">132</span><br><span class="line">&gt;&gt;&gt; fake.msisdn()</span><br><span class="line">&#39;5445934248280&#39;</span><br><span class="line">&gt;&gt;&gt; fake.phone_number() # 手机号</span><br><span class="line">&#39;18666613199&#39;</span><br></pre></td></tr></table></figure><h2 id="14-身份证号码"><a href="#14-身份证号码" class="headerlink" title="14.身份证号码"></a>14.身份证号码</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.ssn(min_age&#x3D;18, max_age&#x3D;90)</span><br><span class="line">&#39;460201193310128795&#39;</span><br><span class="line">人物</span><br></pre></td></tr></table></figure><h2 id="15-人物"><a href="#15-人物" class="headerlink" title="15.人物"></a>15.人物</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.suffix_female()</span><br><span class="line">&#39;&#39;</span><br><span class="line">&gt;&gt;&gt; fake.last_name() # 姓</span><br><span class="line">&#39;董&#39;</span><br><span class="line">&gt;&gt;&gt; fake.suffix_male()</span><br><span class="line">&#39;&#39;</span><br><span class="line">&gt;&gt;&gt; fake.first_name_male() # 男性名</span><br><span class="line">&#39;淑兰&#39;</span><br><span class="line">&gt;&gt;&gt; fake.name() # 姓名</span><br><span class="line">&#39;空丹&#39;</span><br><span class="line">&gt;&gt;&gt; fake.first_name() # 名</span><br><span class="line">&#39;凯&#39;</span><br><span class="line">&gt;&gt;&gt; fake.last_name_male() # 男性姓</span><br><span class="line">&#39;却&#39;</span><br><span class="line">&gt;&gt;&gt; fake.name_male() # 女性姓名</span><br><span class="line">&#39;申柳&#39;</span><br><span class="line">&gt;&gt;&gt; fake.romanized_name()</span><br><span class="line">&#39;Xia Xu&#39;</span><br><span class="line">&gt;&gt;&gt; fake.suffix()</span><br><span class="line">&#39;&#39;</span><br><span class="line">&gt;&gt;&gt; fake.first_name_female()</span><br><span class="line">&#39;琴&#39;</span><br><span class="line">&gt;&gt;&gt; fake.last_name_female()</span><br><span class="line">&#39;羿&#39;</span><br><span class="line">&gt;&gt;&gt; fake.prefix_male()</span><br><span class="line">&#39;&#39;</span><br><span class="line">&gt;&gt;&gt; fake.name_female()</span><br><span class="line">&#39;明璐&#39;</span><br><span class="line">&gt;&gt;&gt; fake.prefix_female()</span><br><span class="line">&#39;&#39;</span><br><span class="line">&gt;&gt;&gt; fake.first_romanized_name()</span><br><span class="line">&#39;Li&#39;</span><br><span class="line">&gt;&gt;&gt; fake.prefix()</span><br><span class="line">&#39;&#39;</span><br><span class="line">&gt;&gt;&gt; fake.last_romanized_name()</span><br><span class="line">&#39;Tan&#39;</span><br></pre></td></tr></table></figure><h2 id="16-profile-人物属性"><a href="#16-profile-人物属性" class="headerlink" title="16.profile 人物属性"></a>16.profile 人物属性</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.profile(fields&#x3D;None, sex&#x3D;None)</span><br><span class="line">&#123;&#39;residence&#39;: &#39;广东省呼和浩特县锡山龙街N座 403716&#39;, &#39;sex&#39;: &#39;M&#39;, &#39;website&#39;: [&#39;http:&#x2F;&#x2F;zheng.org&#x2F;&#39;], &#39;birthdate&#39;: &#39;1971-02-20&#39;, &#39;ssn&#39;: &#39;513226197904080189&#39;, &#39;mail&#39;: &#39;jing95@hotmail.com&#39;, &#39;job&#39;: &#39;Ceramics designer&#39;, &#39;current_location&#39;: (Decimal(&#39;-86.424001&#39;), Decimal(&#39;-153.969207&#39;)), &#39;blood_group&#39;: &#39;0+&#39;, &#39;address&#39;: &#39;广东省北京市永川深圳街w座 974761&#39;, &#39;company&#39;: &#39;双敏电子传媒有限公司&#39;, &#39;username&#39;: &#39;xiajiang&#39;, &#39;name&#39;: &#39;韩玉华&#39;&#125;</span><br><span class="line">&gt;&gt;&gt; fake.simple_profile(sex&#x3D;None)</span><br><span class="line">&#123;&#39;mail&#39;: &#39;dengna@yahoo.com&#39;, &#39;address&#39;: &#39;西藏自治区楠市江北闻街v座 524952&#39;, &#39;username&#39;: &#39;guiying17&#39;, &#39;sex&#39;: &#39;F&#39;, &#39;birthdate&#39;: &#39;1995-10-14&#39;, &#39;name&#39;: &#39;姜敏&#39;&#125;</span><br></pre></td></tr></table></figure><h2 id="17-lorem"><a href="#17-lorem" class="headerlink" title="17.lorem"></a>17.lorem</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; fake.paragraphs(nb&#x3D;3, ext_word_list&#x3D;None)</span><br><span class="line">[&#39;当然分析选择得到感觉关于.&#39;, &#39;位置之间应用这种能够.&#39;, &#39;你的处理上海.人员下载主要来自只是首页.图片有些所有详细发布.&#39;]</span><br><span class="line">&gt;&gt;&gt; fake.word(ext_word_list&#x3D;None)</span><br><span class="line">&#39;最大&#39;</span><br><span class="line">&gt;&gt;&gt; fake.text(max_nb_chars&#x3D;200, ext_word_list&#x3D;None)</span><br><span class="line">&#39;相关图片完成以及人民你的.出现语言计划浏览注意处理非常.\n一样制作个人留言留言这是说明.记者主要由于规定点击时候一个.公司时候系列推荐日期.\n汽车学校发现方法.合作学生她的查看各种次数所有或者.\n深圳世界文化不是结果一切.部分具有商品进行评论市场最后.数据回复名称谢谢系列.\n政府威望两个那些一个加入.以下那些需要以下.\n他 们不会工作资源那个这些所有文章.不会目前为什系统.&#39;</span><br><span class="line">&gt;&gt;&gt; fake.sentences(nb&#x3D;3, ext_word_list&#x3D;None)</span><br><span class="line">[&#39;具有信息东西方式教育发布自己.&#39;, &#39;业务类型社会作品方法.&#39;, &#39;帖子作者都是.&#39;]</span><br><span class="line">&gt;&gt;&gt; fake.paragraph(nb_sentences&#x3D;3, variable_nb_sentences&#x3D;True, ext_word_list&#x3D;None)</span><br><span class="line">&#39;不能加入最大重要.发现注意免费生产这是.&#39;</span><br><span class="line">&gt;&gt;&gt; fake.words(nb&#x3D;3, ext_word_list&#x3D;None)</span><br><span class="line">[&#39;关于&#39;, &#39;实现&#39;, &#39;首页&#39;]</span><br><span class="line">&gt;&gt;&gt; fake.sentence(nb_words&#x3D;6, variable_nb_words&#x3D;True, ext_word_list&#x3D;None)</span><br><span class="line">&#39;发现成功一点系统空间全国比较.&#39;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> database </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue面试题合集</title>
      <link href="front/vue/vue-interview1/"/>
      <url>front/vue/vue-interview1/</url>
      
        <content type="html"><![CDATA[<p>作者：李棠辉<br>链接：<a href="https://www.jianshu.com/p/e54a9a34a773">https://www.jianshu.com/p/e54a9a34a773</a><br>来源：简书<br>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。  </p><h2 id="一-请谈谈Vue中的MVVM模式"><a href="#一-请谈谈Vue中的MVVM模式" class="headerlink" title="一. 请谈谈Vue中的MVVM模式"></a>一. 请谈谈Vue中的MVVM模式</h2><p>MVVM全称是Model-View-ViewModel</p><p>Vue是以数据为驱动的,<code>Vue</code>自身将<code>DOM</code>和数据进行绑定,一旦创建绑定,DOM和数据将保持同步,每当数据发生变化,<code>DOM</code>会跟着变化.ViewModel是<code>Vue</code>的核心,他是<code>Vue</code>的一个实例.</p><p><code>Vue</code>实例时作用域某个HTML元素上的这个HTML元素可以是body,也可以是某个<code>id</code>所指代的元素.</p><p>DOMListeners和DataBindings是实现双向绑定的关键。DOMListeners监听页面所有View层DOM元素的变化，当发生变化，Model层的数据随之变化；DataBindings监听Model层的数据，当数据发生变化，View层的DOM元素随之变化。</p><h2 id="二-v-show和v-if指令的共同点和不同点"><a href="#二-v-show和v-if指令的共同点和不同点" class="headerlink" title="二. v-show和v-if指令的共同点和不同点?"></a>二. <code>v-show</code>和<code>v-if</code>指令的共同点和不同点?</h2><ul><li><code>v-show</code>指令是通过修改元素的displayCSS属性让其显示或者隐藏</li><li><code>v-if</code>指令是直接销毁和重建DOM达到让元素显示和隐藏的效果</li></ul><h2 id="三-如何让CSS只在当前组件中起作用"><a href="#三-如何让CSS只在当前组件中起作用" class="headerlink" title="三. 如何让CSS只在当前组件中起作用?"></a>三. 如何让CSS只在当前组件中起作用?</h2><p>将当前组件的<code>&lt;style&gt;</code>修改为<code>&lt;style scoped&gt;</code></p><h2 id="四-lt-keep-alive-gt-lt-keep-alive-gt-的作用是什么"><a href="#四-lt-keep-alive-gt-lt-keep-alive-gt-的作用是什么" class="headerlink" title="四. &lt;keep-alive&gt;&lt;/keep-alive&gt;的作用是什么?"></a>四. <code>&lt;keep-alive&gt;&lt;/keep-alive&gt;</code>的作用是什么?</h2><p><code>&lt;keep-alive&gt;&lt;/keep-alive&gt;</code> 包包裹动态组件时,会缓存不活动的组建实例,主要用于保留组件状态或避免重新渲染.</p><p>人话: 比如有一个列表和一个详情,那么客户就会经常执行</p><p>打开详情,==&gt;&gt;&gt;返回列表==&gt;&gt;&gt;打开详情…</p><p>这样的话列表和详情都是一个频率很高的页面,那么就可以对列表组件使用<keep-alive></keep-alive>进行缓存,这样sb用户每次返回列表的时候,都能从缓存中快速渲染,而不是重新加载数据.</p><h2 id="五-Vue中引入组件的步骤"><a href="#五-Vue中引入组件的步骤" class="headerlink" title="五.Vue中引入组件的步骤?"></a>五.Vue中引入组件的步骤?</h2><ol><li>采用ES6的import…from… 语法或commonJS的require()方法引入组件</li><li>对组件进行注册,代码如下:<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 注册</span></span><br><span class="line">Vue.component(<span class="string">&#x27;my-component&#x27;</span>,&#123;</span><br><span class="line">    template:<span class="string">&#x27;&lt;div&gt;A custom component!&lt;/div&gt;&#x27;</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure></li><li>使用组件<code>&lt;my-component&gt;&lt;/my-component&gt;</code></li></ol><h2 id="六-指令v-el的作用是什么"><a href="#六-指令v-el的作用是什么" class="headerlink" title="六.指令v-el的作用是什么?"></a>六.指令v-el的作用是什么?</h2><p>提供一个在页面上已存在的DOM元素作为Vue实例的挂载目标.可以是CSS选择器,也可以是一个HTMLElemen实例. </p><h2 id="七-在Vue中使用插件的步骤"><a href="#七-在Vue中使用插件的步骤" class="headerlink" title="七. 在Vue中使用插件的步骤"></a>七. 在Vue中使用插件的步骤</h2><ol><li>采用ES6的import…from… 语法或commonJS的require()方法引入插件</li><li>使用全局方法Vue.use(plugin)使用插件,可以传入一个选项对象Vue.use(MyPlugin,{someOption:true})</li></ol><h2 id="八-请列举出3个Vue中常用的生命周期钩子函数"><a href="#八-请列举出3个Vue中常用的生命周期钩子函数" class="headerlink" title="八.请列举出3个Vue中常用的生命周期钩子函数?"></a>八.请列举出3个Vue中常用的生命周期钩子函数?</h2><ol><li><p>created:实例已经创建完成之后自动调用,在这一步,实例已经完成数据观测,属性和方法的运算,watch/event事件回调.然而,挂载阶段还没有开始,$el属性目前还不可见</p></li><li><p>mounted:<code>el</code>呗新创建出来<code>vm.$el</code>替换,并挂载到实例上去之后调用该钩子.如果<code>root</code>实例挂载了一个文档内元素,当mounted被调用时<code>vm.$el</code>也在文档内.</p></li><li><p>activated:<code>keep-alive</code>组件激活时调用</p></li></ol><h2 id="九-请简述一下Vuex的原理和使用方法"><a href="#九-请简述一下Vuex的原理和使用方法" class="headerlink" title="九. 请简述一下Vuex的原理和使用方法"></a>九. 请简述一下Vuex的原理和使用方法</h2><p>一个应用可以看做是有上面三部分构成,组成<code>View</code>,<code>Actions</code>,<code>State</code>,数据的流动也是View=&gt;Actions=&gt;State=&gt;View以此达到数据的单向流动,但是项目较大的,组件嵌套过多的时候,多组件共享同一个State会在数据传递时出现很多问题.Vuex就是为了解决这些问题而产生的.</p><p>Vuex可以被看做项目中所有组件的数据中心,我们将所有组件中共享的State抽离出来,任何组件都可以访问和操作我们是数据中心.</p><p>上图可以很好的说明VUex的组成,一个实例化的Vuex.Store有state,mutation和actions三个属性组成:</p><ul><li>state中保存着公有数据</li><li>改变state中的数据有且只有通过mutation中的方法,且mutation中的方法必须是同步的</li><li>如果要写异步的方法需要在actions中,并通过commit到mutations中进行state中数据的更改.</li></ul><h2 id="十-请谈谈vue框架和Angular-js和React的不同"><a href="#十-请谈谈vue框架和Angular-js和React的不同" class="headerlink" title="十.请谈谈vue框架和Angular.js和React的不同"></a>十.请谈谈vue框架和Angular.js和React的不同</h2><h3 id="react"><a href="#react" class="headerlink" title="react"></a>react</h3><p>react和Vue有许多相似之处,它们都有:</p><ul><li>使用virtual Dom</li><li>提供了响应式(Reactive)和组件化(composable)的视图组件.</li><li>将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库.</li></ul><p>由于有着众多的相似之处,我们会用更多的时间在这一块进行比较.这里我们不知保证技术内容的准确性,同时也兼顾了平衡的考量.我们需要承认react比Vue更好的地方,比如更丰富的生态系统.</p><h3 id="运行时的性能"><a href="#运行时的性能" class="headerlink" title="运行时的性能"></a>运行时的性能</h3><p>react和Vue都是非常快的,所以速度并不是它们之中做选择的决定性因素.对于具体的数据表现,再说吧!</p><p>优化<br>在react应用中,当某个组件的状态发生改变时,它会以该组件为跟,重洗渲染整个组件子树。</p><p>如要避免不必要的子组件的重渲染，你需要在所有可能的地方使用 PureComponent，或是手动实现 shouldComponentUpdate 方法。同时你可能会需要使用不可变的数据结构来使得你的组件更容易被优化。</p><p>然而，使用 PureComponent 和 shouldComponentUpdate 时，需要保证该组件的整个子树的渲染输出都是由该组件的 props 所决定的。如果不符合这个情况，那么此类优化就会导致难以察觉的渲染结果不一致。这使得 React 中的组件优化伴随着相当的心智负担。</p><p>在 Vue 应用中，组件的依赖是在渲染过程中自动追踪的，所以系统能精确知晓哪个组件确实需要被重渲染。你可以理解为每一个组件都已经自动获得了 shouldComponentUpdate，并且没有上述的子树问题限制。</p><p>Vue 的这个特点使得开发者不再需要考虑此类优化，从而能够更好地专注于应用本身。</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> front </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于TeX排版系统简介</title>
      <link href="comic/tex/"/>
      <url>comic/tex/</url>
      
        <content type="html"><![CDATA[<h2 id="先说说TEX和LATEX"><a href="#先说说TEX和LATEX" class="headerlink" title="先说说TEX和LATEX"></a>先说说TEX和LATEX</h2><h3 id="TEX"><a href="#TEX" class="headerlink" title="TEX"></a>TEX</h3><p>TEX是诞生于20世纪70年代末到80年代初的一款计算机排版软件，而且是命令行格式的（如下图），用来排版高质量的书籍，特别是包含有数学公式的书籍。TEX以追求高质量为目标，很早就实现了矢量描述的计算机字体、细致的分页断行算法和数学排版功能，因其数学排版能力得到了学术界的广泛使用，也启发了后来复杂的商业计算机排版软件。</p><h3 id="LATEX"><a href="#LATEX" class="headerlink" title="LATEX"></a>LATEX</h3><p>LATEX开始于20世纪80年代初，是Leslie Lamport博士为了编写自己的一部书籍而设计的。LATEX是对TEX的封装和拓展，实际上就是用TEX语言编写的一组宏代码，拥有比原来TEX格式（Plain TEX）更为规范的命令和一整套预定义的格式，隐藏了不少排版方面的细节，可以让完全不懂排版理论的学者们也可以比较容易地将书籍和文稿排版出来。</p><h2 id="再说TEXLive和Lyx"><a href="#再说TEXLive和Lyx" class="headerlink" title="再说TEXLive和Lyx"></a>再说TEXLive和Lyx</h2><p>由于TEX/LATEX并不是单独的程序，现在的TEX系统都是复杂的软件包，里面包含各种排版的引擎、编译脚本、格式转换工具、管理界面、配置文件、支持工具、字体及数以千计的宏包和文档。一个TEX发行版就是把所有这样的部件都集合起来，打包发布的软件。</p><h3 id="TEXLive"><a href="#TEXLive" class="headerlink" title="TEXLive"></a>TEXLive</h3><p>TEXLive是TEX的一个发行版，它是由TUG（TEX User Group，TEX用户组）发布的，可以在类UNIX/Linux、Mac OS X和Windows等不同的操作系统平台下安装使用，并且提供相当可靠的工作环境。<br>常用的两种安装方式：<br>1.从TEXLive光盘进行安装；<br>2.从网络在线安装（参见本人博文：<a href="http://blog.csdn.net/qq_33429968/article/details/62928742%EF%BC%89%E3%80%82">http://blog.csdn.net/qq_33429968/article/details/62928742）。</a></p><h3 id="Lyx"><a href="#Lyx" class="headerlink" title="Lyx"></a>Lyx</h3><p>Lyx是一个编辑软件，简单点说就是，Lyx = Word面孔 + LaTeX核心。</p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> entertainment </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>RESTful架构风格简介</title>
      <link href="develop/restful/"/>
      <url>develop/restful/</url>
      
        <content type="html"><![CDATA[<h1 id="RESTful架构风格"><a href="#RESTful架构风格" class="headerlink" title="RESTful架构风格"></a>RESTful架构风格</h1><p>RESTful架构风格最初由Roy T. Fielding（HTTP/1.1协议专家组负责人）在其2000年的博士学位论文中提出。HTTP就是该架构风格的一个典型应用。从其诞生之日开始，它就因其可扩展性和简单性受到越来越多的架构师和开发者们的青睐。一方面，随着云计算和移动计算的兴起，许多企业愿意在互联网上共享自己的数据、功能；另一方面，在企业中，RESTful API（也称RESTful Web服务）也逐渐超越SOAP成为实现SOA的重要手段之一。时至今日，RESTful架构风格已成为企业级服务的标配。</p><p>REST即Representational State Transfer的缩写，可译为”表现层状态转化”。REST最大的几个特点为：资源、统一接口、URI和无状态。</p><h2 id="RESTful架构风格的特点"><a href="#RESTful架构风格的特点" class="headerlink" title="RESTful架构风格的特点"></a>RESTful架构风格的特点</h2><h3 id="资源"><a href="#资源" class="headerlink" title="资源"></a>资源</h3><p>所谓”资源”，就是网络上的一个实体，或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务，总之就是一个具体的实在。资源总要通过某种载体反应其内容，文本可以用txt格式表现，也可以用HTML格式、XML格式表现，甚至可以采用二进制格式；图片可以用JPG格式表现，也可以用PNG格式表现；JSON是现在最常用的资源表示格式。</p><p>结合我的开发实践，我对资源和数据理解如下：</p><p>资源是以json(或其他Representation)为载体的、面向用户的一组数据集，资源对信息的表达倾向于概念模型中的数据：</p><p>资源总是以某种Representation为载体显示的，即序列化的信息<br>常用的Representation是json(推荐)或者xml（不推荐）等<br>Represntation 是REST架构的表现层<br>相对而言，数据（尤其是数据库）是一种更加抽象的、对计算机更高效和友好的数据表现形式，更多的存在于逻辑模型中</p><p>资源和数据关系如下：</p><p>resource vs data</p><h3 id="统一接口"><a href="#统一接口" class="headerlink" title="统一接口"></a>统一接口</h3><p>RESTful架构风格规定，数据的元操作，即CRUD(create, read, update和delete,即数据的增删查改)操作，分别对应于HTTP方法：GET用来获取资源，POST用来新建资源（也可以用于更新资源），PUT用来更新资源，DELETE用来删除资源，这样就统一了数据操作的接口，仅通过HTTP方法，就可以完成对数据的所有增删查改工作。</p><p>即：</p><p>GET（SELECT）：从服务器取出资源（一项或多项）。<br>POST（CREATE）：在服务器新建一个资源。<br>PUT（UPDATE）：在服务器更新资源（客户端提供完整资源数据）。<br>PATCH（UPDATE）：在服务器更新资源（客户端提供需要修改的资源数据）。<br>DELETE（DELETE）：从服务器删除资源。</p><h3 id="URI"><a href="#URI" class="headerlink" title="URI"></a>URI</h3><p>可以用一个URI（统一资源定位符）指向资源，即每个URI都对应一个特定的资源。要获取这个资源，访问它的URI就可以，因此URI就成了每一个资源的地址或识别符。</p><p>一般的，每个资源至少有一个URI与之对应，最典型的URI即URL。</p><h3 id="无状态"><a href="#无状态" class="headerlink" title="无状态"></a>无状态</h3><p>所谓无状态的，即所有的资源，都可以通过URI定位，而且这个定位与其他资源无关，也不会因为其他资源的变化而改变。有状态和无状态的区别，举个简单的例子说明一下。如查询员工的工资，如果查询工资是需要登录系统，进入查询工资的页面，执行相关操作后，获取工资的多少，则这种情况是有状态的，因为查询工资的每一步操作都依赖于前一步操作，只要前置操作不成功，后续操作就无法执行；如果输入一个url即可得到指定员工的工资，则这种情况是无状态的，因为获取工资不依赖于其他资源或状态，且这种情况下，员工工资是一个资源，由一个url与之对应，可以通过HTTP中的GET方法得到资源，这是典型的RESTful风格。</p><h1 id="简要概括"><a href="#简要概括" class="headerlink" title="简要概括"></a>简要概括</h1><ul><li>本真REST + OAuth是RESTful 是微服务的标配</li><li>Basic Auth只在开发环境中使用</li><li>设计合理的资源</li><li>用正确的HTTP方法对数据发正确的请求<h1 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接:"></a>参考链接:</h1><a href="http://www.ruanyifeng.com/blog/2011/09/restful.html">理解RESTful架构</a></li></ul><p><a href="https://www.jianshu.com/p/05dd65881859">RESTFUL风格架构</a></p><p><a href="https://www.jianshu.com/p/65ab865a5e9f">RESTful 架构风格概述</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>redis笔记01</title>
      <link href="database/redis/2020/redis-note1/"/>
      <url>database/redis/2020/redis-note1/</url>
      
        <content type="html"><![CDATA[<h2 id="NoSQL"><a href="#NoSQL" class="headerlink" title="NoSQL"></a>NoSQL</h2><p>NoSQL: 即Not-Only SQL(泛指非关系型数据库),作为关系型数据库的补充/<br>作用:应对基于海量用户和海量数据前提下的数据处理问题.<br>特征:</p><ul><li>可扩容,可伸缩</li><li>大数据量下高性能</li><li>灵活的数据模型</li><li>高可用<br>常见NoSQL数据库:</li><li>Redis</li><li>memcache</li><li>HBase</li><li>MongoDB<br>解决方案(电商场景)</li></ul><ol><li>商品基本信息<ul><li>名称</li><li>价格</li><li>厂商</li></ul></li><li>商品附加信息<ul><li>描述</li><li>详情</li><li>评论</li></ul></li><li>图片信息  分布式文件系统</li><li>搜索关键字  ES,Lucene, solr</li><li>热点信息(这个信息可能是上面的任意一种)<ul><li>高频</li><li>波段性</li></ul></li></ol><h2 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>Redis(REmote DIctionary Server)是一种C语言开发的一个开源的高性能键值对(key-value)数据库.</p><h3 id="特征"><a href="#特征" class="headerlink" title="特征"></a>特征</h3><ol><li>数据之间没有必然的关联关系</li><li>内部采用单线程机制进行工作</li><li>高性能.官方提供测试数据,50个并发执行100000个请求,读的速度是110000次/s,写的速度是81000次/s/</li><li>多数据类型支持<ul><li>字符串类型     String</li><li>列表类型       List</li><li>散列类型       Hash</li><li>集合类型       set</li><li>有序集合类型    sorted_set</li></ul></li><li>持久化支持.可以进行数据灾难恢复</li></ol><h3 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h3><ul><li>为热点数据加速查询(主要场景),比如热点商品,热点新闻,热点资讯,推广类等高访问量信息等</li><li>任务队列,如秒杀,抢购,购票排队等</li><li>即时信息查询,如各位排行榜,各类网站访问统计,公交到站信息,在线人数信息(聊天室,网站),设备信号等</li><li>时效性信息控制,如验证码控制,投票控制等</li><li>分布式数据共享,如分布式集群架构中的session分离</li><li>消息队列</li><li>分布式锁</li></ul><h2 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h2><p>Linux版(适合于企业级开发)</p><ul><li>Redis高级开始使用</li><li>以4.0版本作为主版本<br>Windows版本(适合零基础学习) </li><li>Redis入门使用</li><li>以3.2版本作为主版本</li><li>下载地址:<a href="https://github.com/MSOpenTech/redis/tags">https://github.com/MSOpenTech/redis/tags</a></li></ul><h2 id="命令行模式工具使用思考"><a href="#命令行模式工具使用思考" class="headerlink" title="命令行模式工具使用思考"></a>命令行模式工具使用思考</h2><ul><li>功能性命令</li><li>清楚屏幕信息</li><li>帮助信息查询</li><li>推出指令</li></ul><h2 id="信息添加"><a href="#信息添加" class="headerlink" title="信息添加"></a>信息添加</h2><ul><li>功能:设置key查询对应的</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>redis笔记02</title>
      <link href="database/redis/2020/redis-note2/"/>
      <url>database/redis/2020/redis-note2/</url>
      
        <content type="html"><![CDATA[<h2 id="String类型数据的扩展操作"><a href="#String类型数据的扩展操作" class="headerlink" title="String类型数据的扩展操作"></a>String类型数据的扩展操作</h2><p>解决方案</p><ul><li>设置数据具有指定的生命周期<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">setex key seconds value</span><br><span class="line">psetex key milliseconds value</span><br></pre></td></tr></table></figure></li></ul><p>redis控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作</p><h2 id="String类型数据操作的注意事项"><a href="#String类型数据操作的注意事项" class="headerlink" title="String类型数据操作的注意事项"></a>String类型数据操作的注意事项</h2><ul><li>数据操作不成功的反馈与数据正常操作之间的差异<ul><li>表示运行结果是否成功<ul><li>(integer)0 -&gt; false 失败</li><li>(integer)1 -&gt; true 成功</li></ul></li><li>表示运行结果值<ul><li>(integer)3 -&gt; 3   3个</li><li>(integer)1 -&gt; 1   1个</li></ul></li></ul></li><li>数据未获取到<br>  (nil) 等同于 null</li><li>数据最大存储量<ul><li>512MB 没有必要来探讨上限问题</li></ul></li><li>数值计算最大范围(Java中的long的最大值)<ul><li>9223372036854775807</li></ul></li></ul><h1 id="目录"><a href="#目录" class="headerlink" title="目录"></a>目录</h1><ul><li>数据类型介绍</li><li>string</li><li>hash</li><li>list</li><li>set</li><li>sorted_set</li><li>数据类型实践案例</li></ul><h2 id="hash类型"><a href="#hash类型" class="headerlink" title="hash类型"></a>hash类型</h2><p>存储的困惑<br>对象类数据的存储如果具有较频繁的更新需求操作会显得比较笨重</p><ul><li>新的存储需求:对一系列的数据进行编组,方便管理,典型应用存储对象信息</li><li>需要的存储结构:一个存储空间保存多个键值对数据</li><li>hash类型:底层使用哈希表结构实现数据存储<h3 id="hash存储结构优化"><a href="#hash存储结构优化" class="headerlink" title="hash存储结构优化"></a>hash存储结构优化</h3></li><li>如果field数量较少,存储结构优化为类数组结构</li><li>如果field数量较多,存储结构使用hashMap结构</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Xadmin添加用户小组件出错</title>
      <link href="python/Django/python-xadmin/"/>
      <url>python/Django/python-xadmin/</url>
      
        <content type="html"><![CDATA[<p>环境：</p><p>Python 3.5.6</p><p>Django 2.1</p><p>Xadmin</p><p>&nbsp;</p><p>原因：</p><p>render函数在django2.1上有变化</p><p>&nbsp;</p><p>解决方案：</p><p>1.在Python终端输入命令help('xadmin') 查看xadmin安装位置 得到如下输出</p><div class="cnblogs_code"><pre><span style="color: #000000;">FILE    </span>/root/anaconda3/envs/learndjango/lib/python3.<span style="color: #800080;">5</span>/site-packages/xadmin/__init__.py</pre></div><p>2.进入xadmin安装路径，编辑xadmin/views/dashboard.py</p><div class="cnblogs_code"><pre> 36     <span style="color: #008000;">#</span><span style="color: #008000;">render() got an unexpected keyword argument 'renderer'</span> 37     <span style="color: #008000;">#</span><span style="color: #008000;">修改bug, 添加renderer</span> 38     <span style="color: #008000;">#</span><span style="color: #008000;">by prism 2018/10/4</span> 39     <span style="color: #0000ff;">def</span> render(self, name, value, attrs=None, renderer=None):</pre></div><p>&nbsp;</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue.js笔记01</title>
      <link href="front/vue/note/vue-note1/"/>
      <url>front/vue/note/vue-note1/</url>
      
        <content type="html"><![CDATA[<h1 id="一-邂逅Vuejs"><a href="#一-邂逅Vuejs" class="headerlink" title="一. 邂逅Vuejs"></a>一. 邂逅Vuejs</h1><h2 id="1-1-认识Vuejs"><a href="#1-1-认识Vuejs" class="headerlink" title="1.1 认识Vuejs"></a>1.1 认识Vuejs</h2><p>-[ ] 为什么学习Vue<br>-[ ] Vue读音<br>-[x] Vue的渐进式<br>-[ ] Vue特点</p><h2 id="1-2-安装Vuejs"><a href="#1-2-安装Vuejs" class="headerlink" title="1.2 安装Vuejs"></a>1.2 安装Vuejs</h2><p>-[x] CDN引入<br>-[x] 下载引入<br>-[x] npm安装</p><h2 id="1-3-Vue的初体验"><a href="#1-3-Vue的初体验" class="headerlink" title="1.3 Vue的初体验"></a>1.3 Vue的初体验</h2><p>-[x] Hello Vuejs<br>    - Mustache语法-&gt; 体验Vue的响应式<br>-[x] Vue 列表展示<br>    - v-for<br>    - 后面给数组追加元素的时候,新的元素也可以中渲染出来<br>-[x] Vue 计数器小案例<br>    - 事件监听:click-&gt;methods</p><h2 id="1-4-Vue中的MVVM"><a href="#1-4-Vue中的MVVM" class="headerlink" title="1.4 Vue中的MVVM"></a>1.4 Vue中的MVVM</h2><h2 id="1-5-创建Vue时-options可以放那些东西"><a href="#1-5-创建Vue时-options可以放那些东西" class="headerlink" title="1.5 创建Vue时,options可以放那些东西"></a>1.5 创建Vue时,options可以放那些东西</h2><p>-[x] el:<br>-[x] data:<br>-[x] methods:<br>-[x] 生命周期函数</p><h1 id="二-插值语法"><a href="#二-插值语法" class="headerlink" title="二. 插值语法"></a>二. 插值语法</h1><p>-[x] Mustache语法<br>-[ ] v-once<br>-[x] v-html<br>-[ ] v-text<br>-[ ] v-pre:{ {} }<br>-[ ] v-cloak:斗篷</p><h1 id="三-v-bind"><a href="#三-v-bind" class="headerlink" title="三. v-bind"></a>三. v-bind</h1><h2 id="3-1-v-bind绑定基本属性"><a href="#3-1-v-bind绑定基本属性" class="headerlink" title="3.1 v-bind绑定基本属性"></a>3.1 v-bind绑定基本属性</h2><p>-[x] v-bind:sr<br>-[x] :href</p><h2 id="3-2-v-bind动态绑定class"><a href="#3-2-v-bind动态绑定class" class="headerlink" title="3.2 v-bind动态绑定class"></a>3.2 v-bind动态绑定class</h2><p>-[x] 对象语法: 作业:class=’{类名:boolean}’<br>-[x] 数组语法</p><h1 id="四-计算属性"><a href="#四-计算属性" class="headerlink" title="四. 计算属性"></a>四. 计算属性</h1><h2 id="案例一-firstName-lastName"><a href="#案例一-firstName-lastName" class="headerlink" title="案例一:firstName+lastName"></a>案例一:firstName+lastName</h2><p>页面</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/vue&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Title<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--作业需求,:点击我们列表中的哪一项,那么该项的文字变成红色--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--最大的div--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>&#123;&#123;firstName&#125;&#125;&#123;&#123;lastName&#125;&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>&#123;&#123;firstName+lastName&#125;&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--    这个不用加小括号--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>&#123;&#123;fullName&#125;&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>&#123;&#123;getFullName()&#125;&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./index.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>js</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app = <span class="keyword">new</span> Vue(&#123;</span><br><span class="line">    el: <span class="string">&#x27;#app&#x27;</span>,</span><br><span class="line">    data: &#123;</span><br><span class="line">        firstName: <span class="string">&quot;victor&quot;</span>,</span><br><span class="line">        lastName: <span class="string">&quot;fengming&quot;</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">    computed: &#123;</span><br><span class="line">    <span class="comment">//    这里一般不加动词的函数</span></span><br><span class="line">        fullName: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">this</span>.firstName + <span class="built_in">this</span>.lastName</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br><span class="line">    &#125;,</span><br><span class="line">    methods: &#123;</span><br><span class="line">        getFullName: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">this</span>.firstName + <span class="built_in">this</span>.lastName</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="案例二-books-gt-price"><a href="#案例二-books-gt-price" class="headerlink" title="案例二:books -&gt; price"></a>案例二:books -&gt; price</h2><p>页面</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/vue&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Title<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--最大的div--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>总价格:&#123;&#123;totalPrice&#125;&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./index.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>js</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app = <span class="keyword">new</span> Vue(&#123;</span><br><span class="line">    el: <span class="string">&#x27;#app&#x27;</span>,</span><br><span class="line">    data: &#123;</span><br><span class="line">        books: [</span><br><span class="line">            &#123;<span class="attr">id</span>: <span class="number">110</span>, <span class="attr">name</span>: <span class="string">&quot;Unix编程艺术&quot;</span>, <span class="attr">price</span>: <span class="number">24</span>&#125;,</span><br><span class="line">            &#123;<span class="attr">id</span>: <span class="number">111</span>, <span class="attr">name</span>: <span class="string">&quot;代码大全&quot;</span>, <span class="attr">price</span>: <span class="number">25</span>&#125;,</span><br><span class="line">            &#123;<span class="attr">id</span>: <span class="number">112</span>, <span class="attr">name</span>: <span class="string">&quot;深入理解计算机&quot;</span>, <span class="attr">price</span>: <span class="number">675</span>&#125;,</span><br><span class="line">            &#123;<span class="attr">id</span>: <span class="number">113</span>, <span class="attr">name</span>: <span class="string">&quot;现代操作系统&quot;</span>, <span class="attr">price</span>: <span class="number">565</span>&#125;,</span><br><span class="line">        ],</span><br><span class="line">    &#125;,</span><br><span class="line">    computed: &#123;</span><br><span class="line">        <span class="comment">// 高级函数</span></span><br><span class="line">        <span class="comment">// filter/map/reduce,</span></span><br><span class="line">        totalPrice: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="comment">// // 普通的low逼写法</span></span><br><span class="line">            <span class="comment">// let result = 0;</span></span><br><span class="line">            <span class="comment">// for (let i = 0; i &lt; this.books.length; i++) &#123;</span></span><br><span class="line">            <span class="comment">//     result += this.books[i].price</span></span><br><span class="line">            <span class="comment">// &#125;</span></span><br><span class="line">            <span class="comment">// return result;</span></span><br><span class="line">            <span class="comment">// // ES6写法1</span></span><br><span class="line">            <span class="comment">// for (let i in this.books) &#123;</span></span><br><span class="line">            <span class="comment">//     books[i]</span></span><br><span class="line">            <span class="comment">// &#125;</span></span><br><span class="line">            <span class="comment">// // ES6写法2</span></span><br><span class="line">            <span class="comment">// for (let book of this.books) &#123;</span></span><br><span class="line">            <span class="comment">//     book</span></span><br><span class="line">            <span class="comment">// &#125;</span></span><br><span class="line">            <span class="comment">// return this.books.reduce();</span></span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="comment">//    计算属性和method在执行的时候有很大区别,</span></span><br><span class="line">        <span class="comment">//    这个计算属性不会多次执行</span></span><br><span class="line">        <span class="comment">//    他是有缓存的,</span></span><br><span class="line">    &#125;,</span><br><span class="line">    methods: &#123;</span><br><span class="line">        getmessage: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">this</span>.message</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><a href="https://www.bilibili.com/video/av89760569?p=23">ori_link</a></p><h1 id="var和let"><a href="#var和let" class="headerlink" title="var和let"></a>var和let</h1><p>JavaScript设计的缺陷,在设计之初没有想过现在发展的这么完善</p><p>let具有块级作用域,而var没有</p><p>ES5中没有闭包,ES6中加入了闭包</p><p>没有闭包就会导致在for循环的时候i被不必要的更新</p><h1 id="const的使用"><a href="#const的使用" class="headerlink" title="const的使用"></a>const的使用</h1><p>常量尽量用const,优先使用const,只有需要改变的才使用let</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MySQL 数据库导出导入操作</title>
      <link href="database/mysql/mysql-output/"/>
      <url>database/mysql/mysql-output/</url>
      
        <content type="html"><![CDATA[<div id="content_views" class="markdown_views">    <!-- flowchart 箭头图标 勿删 -->    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block"              style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>    </svg>    <p>有时需要将 MySQL 数据库中的数据导入到其它的数据库中，这里以从 Ubuntu 系统的 MySQL 数据库导出 zabbix 这个数据库到 Windows 系统中的MySQL 为例。</p><pre><code>&lt;h2 id=&quot;导出数据库&quot;&gt;&lt;a name=&quot;t0&quot;&gt;&lt;/a&gt;&lt;a name=&quot;t0&quot;&gt;&lt;/a&gt;导出数据库&lt;/h2&gt;&lt;p&gt;导出数据其实非常方便，比如将 MySQL 中的 zabbix 这个数据库导出到当前文件夹，首先切换到 root 用户，然后再切换到 Document    这个目录，这样就可以直接将数据库导出到这个目录了，当然，指定特定目录也是可以的，接着执行&lt;/p&gt;&lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs lasso has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                           style=&quot;position: unset;&quot;&gt;mysqldump &lt;span        class=&quot;hljs-attribute&quot;&gt;-uroot&lt;/span&gt; &lt;span class=&quot;hljs-attribute&quot;&gt;-ppassword&lt;/span&gt; zabbix&lt;span        class=&quot;hljs-subst&quot;&gt;&amp;gt;&lt;/span&gt;zabbix&lt;span class=&quot;hljs-built_in&quot;&gt;.&lt;/span&gt;sql&lt;div class=&quot;hljs-button &#123;2&#125;&quot;                                                                                        data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul        class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;-p&lt;/code&gt;后是自己 MySQL 数据库密码，如果&lt;code&gt;&amp;gt;&lt;/code&gt;后不指定目录，则导出到当前文件夹内。&lt;/p&gt;&lt;h2 id=&quot;导入数据库&quot;&gt;&lt;a name=&quot;t1&quot;&gt;&lt;/a&gt;&lt;a name=&quot;t1&quot;&gt;&lt;/a&gt;导入数据库&lt;/h2&gt;&lt;p&gt;导入到 windows 系统数据库也很简单，可以使用客户端导入，这里使用命令行的形式导入，首先使用 &lt;code&gt;WIN + R&lt;/code&gt;快捷键调出“运行”窗口，然后输入&lt;code&gt;cmd&lt;/code&gt;打开命令行终端，依次执行如下命令&lt;/p&gt;&lt;ul&gt;    &lt;li&gt;登陆数据库&lt;/li&gt;&lt;/ul&gt;&lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs lasso has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                           style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-subst&quot;&gt;&amp;gt;&lt;/span&gt;mysql &lt;span        class=&quot;hljs-attribute&quot;&gt;-uroot&lt;/span&gt; &lt;span class=&quot;hljs-attribute&quot;&gt;-ppassword&lt;/span&gt;&lt;div        class=&quot;hljs-button &#123;2&#125;&quot; data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li        style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;&lt;ul&gt;    &lt;li&gt;创建数据库&lt;/li&gt;&lt;/ul&gt;&lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs oxygene has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                           style=&quot;position: unset;&quot;&gt;&amp;gt;&lt;span class=&quot;hljs-keyword&quot;&gt;CREATE&lt;/span&gt; DATABASE zabbix;&lt;div        class=&quot;hljs-button &#123;2&#125;&quot; data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li        style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;&lt;ul&gt;    &lt;li&gt;导入数据&lt;/li&gt;&lt;/ul&gt;&lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs tex has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                           style=&quot;position: unset;&quot;&gt;&amp;gt;use zabbix;</code></pre><p>&gt;set names utf8;<br>&gt;source <span class="hljs-command">\Users</span><span class="hljs-command">\Erik</span><span class="hljs-command">\Desktop</span><span                class="hljs-command">\zabbix</span>.sql<div class="hljs-button {2}" data-title="复制"></div></code><ul            class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li            style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre></p><pre><code>&lt;p&gt;这里&lt;code&gt;\Users\Erik\Desktop\&lt;/code&gt;是&lt;code&gt;zabbix.sql&lt;/code&gt;的存放路径。&lt;/p&gt;&lt;p&gt;这样就将数据导入到 Windows 系统的 MySQL 数据库中了。&lt;/p&gt;&lt;h2 id=&quot;参考资料&quot;&gt;&lt;a name=&quot;t2&quot;&gt;&lt;/a&gt;&lt;a name=&quot;t2&quot;&gt;&lt;/a&gt;参考资料&lt;/h2&gt;&lt;p&gt;Mysql导入导出数据库以及数据表：&lt;a href=&quot;https://my.oschina.net/linuxphp/blog/693650&quot; rel=&quot;nofollow&quot;&gt;https://my.oschina.net/linuxphp/blog/693650&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>mooc后台管理系统设计</title>
      <link href="python/Django/django-mxonline/"/>
      <url>python/Django/django-mxonline/</url>
      
        <content type="html"><![CDATA[<h1 id="摘-要"><a href="#摘-要" class="headerlink" title="摘 要"></a>摘 要</h1><p>本设计采用Python中的Django框架实现Mooc后台管理界面设计,django是一个完整的开源web开源框架,使用起来能够快速的搭建你想要的网站,由于django自带后台管理系统,本设计中后台管理模板采用功能更加强大的Xadmin实现。数据库部分采用mysql5.7,由于django中有自带封装的数据库驱动,所以我们只需要关心框架中的models类的设计即可,只需要将数据表中的类型和关系建立好关系,后台管理系统基本上能够实现表的增删改查功能。  </p><p>关键词：Python;Django;Xadmin;Mysql;</p><h1 id="前-言"><a href="#前-言" class="headerlink" title="前 言"></a>前 言</h1><p> 随着深度学习技术的发展及普及,在线教育领域的发展与人工智能的结合也<br>是愈发紧密。人工智能+教育便能够把人工智能技术渗透到教学的核心环节中,<br>模拟特技老师,从根本上改进学习的理念和方式,这是真正意义上的教育变革。</p><p>在线教育平台通过 VR、AR 结合 AI 算法与技术,构建识别和优化内容模型,<br>进而形成虚拟课堂效果,极大改善在线教育“学习体验、效果差”等顽疾；通过<br>机器视觉、语音语义等技术,自动化批改、归类作业,甚至可以建立一对一的在<br>线辅导,极大提升行业竞争力。</p><p>另外通过科技+教育的深度融合,能够对学生数据进行科学评估,精准发掘<br>每一个学生在学习上的差别,制定个性化学习方案,实现因材施教,赋予孩子未<br>来更多可能。</p><p>与此同时,AI 技术还可广泛用于学校的校园管理、区域的教育管理及教育<br>治理等相关领域,在优化企业运营策略、降低企业运营成本方面有着不可替代的<br>作用。</p><p>目前 VIPKID、哒哒英语、掌门 1 对 1、海风教育等众多 K12 在线教育企业,<br>都已开始布局“AI+教育”产业,随着头部企业涌入,未来教育行业的 AI 浪潮将<br>更加猛烈。而这个项目就是在这种背景下实施的,进行一次教育推广平台的建设。</p><h1 id="1-基本储备"><a href="#1-基本储备" class="headerlink" title="1.基本储备"></a>1.基本储备</h1><h2 id="1-1-Python介绍"><a href="#1-1-Python介绍" class="headerlink" title="1.1 Python介绍"></a>1.1 Python介绍</h2><p>Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。<br>Python 由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。像 Perl 语言一样, Python 源代码同样遵循 GPL(GNU General Public License) 协议。<br>Python具有以下明显的优点：</p><h3 id="（1）优雅体现在python的格式-比如缩进来确定代码块-可避免编程人员进行复杂的嵌套"><a href="#（1）优雅体现在python的格式-比如缩进来确定代码块-可避免编程人员进行复杂的嵌套" class="headerlink" title="（1）优雅体现在python的格式,比如缩进来确定代码块,可避免编程人员进行复杂的嵌套;"></a>（1）优雅体现在python的格式,比如缩进来确定代码块,可避免编程人员进行复杂的嵌套;</h3><h3 id="（2）明确体现在解决问题的方法只有一种最优选项-而perl语言是每个问题有很多最优解-但不利于团队协作"><a href="#（2）明确体现在解决问题的方法只有一种最优选项-而perl语言是每个问题有很多最优解-但不利于团队协作" class="headerlink" title="（2）明确体现在解决问题的方法只有一种最优选项,而perl语言是每个问题有很多最优解,但不利于团队协作;"></a>（2）明确体现在解决问题的方法只有一种最优选项,而perl语言是每个问题有很多最优解,但不利于团队协作;</h3><h3 id="3-有强大的第三方库模块-需要实现复杂功能-只需要调用现有的库-可快速实现功能。20多年的发展-各种库都已经完备-比如-邮件库-爬虫库。"><a href="#3-有强大的第三方库模块-需要实现复杂功能-只需要调用现有的库-可快速实现功能。20多年的发展-各种库都已经完备-比如-邮件库-爬虫库。" class="headerlink" title="(3)有强大的第三方库模块,需要实现复杂功能,只需要调用现有的库,可快速实现功能。20多年的发展,各种库都已经完备,比如:邮件库,爬虫库。"></a>(3)有强大的第三方库模块,需要实现复杂功能,只需要调用现有的库,可快速实现功能。20多年的发展,各种库都已经完备,比如:邮件库,爬虫库。</h3><h3 id="4-可跨平台移植-java有Java的虚拟机-python同样"><a href="#4-可跨平台移植-java有Java的虚拟机-python同样" class="headerlink" title="(4)可跨平台移植,java有Java的虚拟机,python同样;"></a>(4)可跨平台移植,java有Java的虚拟机,python同样;</h3><h3 id="5-是一种面向对象的语言"><a href="#5-是一种面向对象的语言" class="headerlink" title="(5)是一种面向对象的语言;"></a>(5)是一种面向对象的语言;</h3><h3 id="6-是一种可扩展的语言-与C-C-Java结合-。"><a href="#6-是一种可扩展的语言-与C-C-Java结合-。" class="headerlink" title="(6)是一种可扩展的语言(与C,C++,Java结合)。"></a>(6)是一种可扩展的语言(与C,C++,Java结合)。</h3><h2 id="1-2-Django介绍"><a href="#1-2-Django介绍" class="headerlink" title="1.2 Django介绍"></a>1.2 Django介绍</h2><p>Django 是一个高级的 Python 网络框架,可以快速开发安全和可维护的网站。由经验丰富的开发者构建,Django负责处理网站开发中麻烦的部分,因此你可以专注于编写应用程序,而无需重新开发。<br>它是免费和开源的,有活跃繁荣的社区,丰富的文档,以及很多免费和付费的解决方案。</p><h3 id="（1）完备性："><a href="#（1）完备性：" class="headerlink" title="（1）完备性："></a>（1）完备性：</h3><p>Django遵循“功能完备”的理念,提供开发人员可能想要“开箱即用”的几乎所有功能。因为你需要的一切都是一个”产品“的一部分,它们都可以无缝结合在一起,遵循一致性设计原则,并且具有广泛和最新的文档。</p><h3 id="（2）通用性："><a href="#（2）通用性：" class="headerlink" title="（2）通用性："></a>（2）通用性：</h3><p>Django 可以（并已经）用于构建几乎任何类型的网站—从内容管理系统和维基,到社交网络和新闻网站。它可以与任何客户端框架一起工作,并且可以提供几乎任何格式（包括 HTML,Rss源,JSON,XML等）的内容。你正在阅读的网站就是基于Django。在内部,尽管它为几乎所有可能需要的功能（例如几个流行的数据库,模版引擎等）提供了选择,但是如果需要,它也可以扩展到使用其他组件。</p><h3 id="（3）安全性："><a href="#（3）安全性：" class="headerlink" title="（3）安全性："></a>（3）安全性：</h3><p>Django 帮助开发人员通过提供一个被设计为“做正确的事情”来自动保护网站的框架来避免许多常见的安全错误。例如,Django提供了一种安全的方式来管理用户账户和密码,避免了常见的错误,比如将session放在cookie中这种易受攻击的做法（取而代之的是cookies只包含一个密钥,实际数据存储在数据库中）或直接存储密码而不是密码哈希。</p><h3 id="（4）可扩展："><a href="#（4）可扩展：" class="headerlink" title="（4）可扩展："></a>（4）可扩展：</h3><p>Django 使用基于组件的 “无共享” 架构 (架构的每一部分独立于其他架构,因此可以根据需要进行替换或更改). 在不用部分之间有明确的分隔意味着它可以通过在任何级别添加硬件来扩展服务：缓存服务器,数据库服务器或应用程序服务器。一些最繁忙的网站已经成功地缩放了Django,以满足他们的需求（例如Instagram和Disqus,仅举两个例子,可自行添加）。</p><h3 id="（5）可维护性："><a href="#（5）可维护性：" class="headerlink" title="（5）可维护性："></a>（5）可维护性：</h3><p>Django 代码编写是遵照设计原则和模式,鼓励创建可维护和可重复使用的代码。特别是它使用了不要重复自己（DRY）原则,所以没有不必要的重复,减少了代码的数量。Django还将相关功能分组到可重用的“应用程序”中,并且在较低级别将相关代码分组或模块（ 模型视图控制器 (MVC)模式)。</p><h3 id="（6）灵活性："><a href="#（6）灵活性：" class="headerlink" title="（6）灵活性："></a>（6）灵活性：</h3><p>Django 是用Python编写的,它在许多平台上运行。这意味着你不受任务特定的服务器平台的限制,并且可以在许多种类的Linux,Windows和Mac OsX 上运行应用程序。此外,Django得到许多网络托管提供商的好评,他们经常提供特定的基础设施和托管Django网站的文档。</p><h2 id="1-3-Mysql介绍"><a href="#1-3-Mysql介绍" class="headerlink" title="1.3 Mysql介绍"></a>1.3 Mysql介绍</h2><p>MYSQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 使用的 SQL 语言是用于访问数据库的最常用的标准化语言。<br>由于 MySQL 数据库体积小、速度快、总体拥有成本低、开放源代码,其有着广泛的应用,一般中小型网站的开发都选择 MySQL 作为网站数据库。由于其社区版的性能卓越,因此搭配 PHP 和 Apache 服务器可组成良好的开发环境。</p><h1 id="2-需求分析"><a href="#2-需求分析" class="headerlink" title="2.需求分析"></a>2.需求分析</h1><p>建站包括前台功能系统和后台管理系统两大系统组成,分别由不同能力的人员实现,而前台功能系统是属于UI设计类的,后台管理系统是程序类的,因此本设计选择进行后台管理系统设计。<br>由于本设计是后台管理系统,所以需求主要是分为课程管理,认证管理和机构管理三个部分。实现基本功能是对于数据记录的增删改查,附加其它的功能,比如过滤器,排序,分页,筛选等功能。整体建站分析如下图2.1所示：<br>图2.1 整体建站分析</p><h2 id="2-1-课程管理模块"><a href="#2-1-课程管理模块" class="headerlink" title="2.1 课程管理模块"></a>2.1 课程管理模块</h2><p>课程管理模块涉及到关于本站的课程的管理操作,主要的操作包括：课程管理、课程资源管理、课程评论管理和轮播课程管理等。<br>根据以上简单分析,其需要编辑和实现的具体数据和变量如下表2.1所示：<br>表2.1 课程管理模块<br>分类    内容<br>Course(课程)    课程名、描述、详情、等级、学习时长等<br>Lesson(章节)    课程名、章节名、添加时间<br>Video(视频)    课程名、视频名、添加时间<br>CourseResource(课程资源)    课程名、名称、资源文件、添加时间</p><h2 id="2-2-认证和授权管理模块"><a href="#2-2-认证和授权管理模块" class="headerlink" title="2.2 认证和授权管理模块"></a>2.2 认证和授权管理模块</h2><p>认证和授权管理模块是关于用户操作的模块,主要的操作包括：用户管理、组管理、权限管理、用户日志管理等。<br>根据以上简单分析,其需要编辑和实现的具体数据和变量如下表2.2所示：<br>表2.2 认证和授权管理模块<br>组别    分类    内容</p><p>User    UserProfile(用户信息)    昵称、生日、性别、地址<br>    EmailVerify(邮箱验证)    验证码、邮箱、发生类型、时间<br>    Banner(轮廓图)    标题,轮播图、url、顺序</p><p>Operation    UserAsk(用户咨询)    名字、手机号、课程名、时间<br>    CourseComment(用户评论)    用户、课程、评论、时间<br>    UserFavorite(用户收藏)    用户、数据ID、收藏类型、时间<br>    UserMessage(用户消息)    接收用户、消息内容、是否已读<br>    UserCourse(用户课程)    用户、课程、时间</p><h2 id="2-3-机构管理模块"><a href="#2-3-机构管理模块" class="headerlink" title="2.3 机构管理模块"></a>2.3 机构管理模块</h2><p>机构管理模块是关于课程发布机构的模块,由于网站上线后允许不同机构在网站上进行开课活动,因此需要进行机构管理,主要包括：课程机构、课程机构管理、讲轮播图管理等。<br>根据以上简单分析,其需要编辑和实现的具体数据和变量如下表2.3所示：</p><p>表2.3 机构管理模块<br>分类    内容<br>CourseOrg(课程机构)    名称、描述、点击数、收藏数、封面<br>CityDict(城市)    名字、描述、添加时间<br>Teacher(教师)    所属机构、教师名、工作年限、简介</p><h1 id="3-Django模型设计"><a href="#3-Django模型设计" class="headerlink" title="3.Django模型设计"></a>3.Django模型设计</h1><p>模型设计是整个项目的核心部分,直接决定了项目后续的可行性,这里我们分为四个app来进行设计,分别是users,course,organization,operation,如下图3.1所示：</p><p>图3.1 django整体模型设计<br>因此,需要拆成4个app来分别完成以上分析的设计功能,分别是users,course,organization,operation：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">python manage.py startapp users</span><br><span class="line">python manage.py startapp course</span><br><span class="line">python manage.py startapp organization</span><br><span class="line">python manage.py startapp operation</span><br></pre></td></tr></table></figure><h2 id="3-1-users用户"><a href="#3-1-users用户" class="headerlink" title="3.1 users用户"></a>3.1 users用户</h2><p>系统会自动生成user表单,包括：<br>id 主键, password 密码, last_login Django自动记录用户最后登录间。<br>is_superuser 表明用户是否是超级用户(后台管理会用到)。<br>username 用户名字段不要随便改动, email 邮箱<br>is_staff 表示是否是员工(后台管理会用到)。<br>is_active 用户是否是激活状态, date_joined 注册时间。<br>表3.1 扩展表单</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">表名字字段名字段类型字段长度(max_length)是否为空备注其他</span><br><span class="line">UserProfile</span><br><span class="line">管理员gender_choicesenum(&#39;male&#39;,&#39;男&#39;),</span><br><span class="line">(&#39;female&#39;,&#39;女&#39;)性别</span><br><span class="line">nick_nameCharField50昵称</span><br><span class="line">birthdayDateFieldTrue生日</span><br><span class="line">genderCharField10性别choices&#x3D;gender_choices</span><br><span class="line">addressCharField100地址</span><br><span class="line">mobileCharField11True手机号</span><br><span class="line">imageImageField100图片upload_to&#x3D;&#39;image&#x2F;%Y%m&#39;g</span><br><span class="line">add_timeDateTimeField添加时间</span><br></pre></td></tr></table></figure><p>给出users/models.py代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># users/models.py</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"><span class="keyword">from</span> django.contrib.auth.models <span class="keyword">import</span> AbstractUser</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserProfile</span>(<span class="params">AbstractUser</span>):</span></span><br><span class="line">    gender_choices = (</span><br><span class="line">        (<span class="string">&#x27;male&#x27;</span>,<span class="string">&#x27;男&#x27;</span>),</span><br><span class="line">        (<span class="string">&#x27;female&#x27;</span>,<span class="string">&#x27;女&#x27;</span>)</span><br><span class="line">    )</span><br><span class="line">    nick_name = models.CharField(<span class="string">&#x27;昵称&#x27;</span>,max_length=<span class="number">50</span>,default=<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    birthday = models.DateField(<span class="string">&#x27;生日&#x27;</span>,null=<span class="literal">True</span>,blank=<span class="literal">True</span>)</span><br><span class="line">    gender = models.CharField(<span class="string">&#x27;性别&#x27;</span>,max_length=<span class="number">10</span>,\</span><br><span class="line">choices=gender_choices,default=<span class="string">&#x27;female&#x27;</span>)</span><br><span class="line">    adress = models.CharField(<span class="string">&#x27;地址&#x27;</span>,max_length=<span class="number">100</span>,default=<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    mobile = models.CharField(<span class="string">&#x27;手机号&#x27;</span>,max_length=<span class="number">11</span>,\</span><br><span class="line">null=<span class="literal">True</span>,blank=<span class="literal">True</span>)</span><br><span class="line">    image = models.ImageField(upload_to=<span class="string">&#x27;image/%Y%m&#x27;</span>,\</span><br><span class="line">default=<span class="string">&#x27;image/default.png&#x27;</span>,max_length=<span class="number">100</span>)</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        verbose_name = <span class="string">&#x27;用户信息&#x27;</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">return</span> self.username</span><br></pre></td></tr></table></figure><h2 id="3-2-Course-课程"><a href="#3-2-Course-课程" class="headerlink" title="3.2 Course 课程"></a>3.2 Course 课程</h2><p>根据上述需求的分析,课程模型的设计如下表3.2所示：<br>表3.2 course需求表单</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">degree_choicesenum(&quot;cj&quot;, &quot;初级&quot;),</span><br><span class="line">(&quot;zj&quot;, &quot;中级&quot;),</span><br><span class="line">(&quot;gj&quot;, &quot;高级&quot;)课程难度</span><br><span class="line">Course</span><br><span class="line">课程nameCharField50True课程名</span><br><span class="line">descriptionCharField300课程描述</span><br><span class="line">introduceUEditorField600&#39;&#39;课程简介</span><br><span class="line">degreeCharField2cj难度</span><br><span class="line">imageImageField100封面图</span><br><span class="line">tagCharField10&#39;&#39;课程标签</span><br><span class="line">is_bannerBooleanFieldFalse是否轮播</span><br><span class="line">course_orgForeignKeynull&#x3D;True,blank&#x3D;True,所属机构</span><br><span class="line">categoryForeignKey课程类别</span><br><span class="line">teacherForeignKeynull&#x3D;True,blank&#x3D;True,讲师</span><br><span class="line">youneed_knowCharField300&#39;&#39;课程须知</span><br><span class="line">teacher_tellCharField300&#39;&#39;老师告诉你</span><br><span class="line">learn_timesIntegerField0学习时长(分钟)</span><br><span class="line">studentsIntegerField0学习人数</span><br><span class="line">fav_numsIntegerField0收藏人数</span><br><span class="line">click_numsIntegerField0点击数</span><br><span class="line">moneyDecimalField价格</span><br><span class="line">add_timeDateTimeFielddatetime.now添加时间</span><br></pre></td></tr></table></figure><p>给出course/models.py代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</span><br><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Course</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">    DEGREE_CHOICES = (</span><br><span class="line">        (<span class="string">&quot;cj&quot;</span>, <span class="string">&quot;初级&quot;</span>),</span><br><span class="line">        (<span class="string">&quot;zj&quot;</span>, <span class="string">&quot;中级&quot;</span>),</span><br><span class="line">        (<span class="string">&quot;gj&quot;</span>, <span class="string">&quot;高级&quot;</span>)</span><br><span class="line">    )</span><br><span class="line">    name = models.CharField(<span class="string">&quot;课程名&quot;</span>,max_length=<span class="number">50</span>)</span><br><span class="line">    desc = models.CharField(<span class="string">&quot;课程描述&quot;</span>,max_length=<span class="number">300</span>)</span><br><span class="line">    detail = models.TextField(<span class="string">&quot;课程详情&quot;</span>)</span><br><span class="line">    degree = models.CharField(<span class="string">&#x27;难度&#x27;</span>,\</span><br><span class="line">choices=DEGREE_CHOICES, max_length=<span class="number">2</span>)</span><br><span class="line">    learn_times = models.IntegerField(<span class="string">&quot;学习时长(分钟数)&quot;</span>,default=<span class="number">0</span>)</span><br><span class="line">    students = models.IntegerField(<span class="string">&quot;学习人数&quot;</span>,default=<span class="number">0</span>)</span><br><span class="line">    fav_nums = models.IntegerField(<span class="string">&quot;收藏人数&quot;</span>,default=<span class="number">0</span>)</span><br><span class="line">    image = models.ImageField(<span class="string">&quot;封面图&quot;</span>,upload_to=<span class="string">&quot;courses/%Y/%m&quot;</span>,\</span><br><span class="line">max_length=<span class="number">100</span>)</span><br><span class="line">    click_nums = models.IntegerField(<span class="string">&quot;点击数&quot;</span>,default=<span class="number">0</span>)</span><br><span class="line">    add_time = models.DateTimeField(<span class="string">&quot;添加时间&quot;</span>,default=datetime.now,)</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        verbose_name = <span class="string">&quot;课程&quot;</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">return</span> self.name</span><br></pre></td></tr></table></figure><h2 id="3-3-Organization机构"><a href="#3-3-Organization机构" class="headerlink" title="3.3 Organization机构"></a>3.3 Organization机构</h2><p>根据上述需求的分析,机构模型的设计如下表3.3所示：<br>表3.3 organzation机构需求表单</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">表名字字段名字段类型字段长度(max_length)默认值(default)备注</span><br><span class="line">CourseOrg</span><br><span class="line">课程机构基本信息nameCharField50机构名称</span><br><span class="line">descTextField机构描述</span><br><span class="line">click_numsIntegerField0点击数</span><br><span class="line">ORG_CHOICES(&quot;pxjg&quot;, u&quot;培训机构&quot;),</span><br><span class="line">(&quot;gx&quot;, u&quot;高校&quot;),</span><br><span class="line">(&quot;gr&quot;, u&quot;个人&quot;),</span><br><span class="line">categorychoices&#x3D;ORG_CHOICES机构类别</span><br><span class="line">fav_numsIntegerField0收藏数</span><br><span class="line">imageImageField100封面图</span><br><span class="line">addressCharField150机构地址</span><br><span class="line">cityCharField所在城市</span><br><span class="line">ordernumCharField订单数</span><br><span class="line">moneyCharField总钱数</span><br><span class="line">teacher_numCharField教师数</span><br><span class="line">add_timeDateTimeFielddatetime.now添加时间</span><br></pre></td></tr></table></figure><p>给出organization/models.py代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CourseOrg</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">    name = models.CharField(<span class="string">&#x27;机构名称&#x27;</span>,max_length=<span class="number">50</span>)</span><br><span class="line">    desc = models.TextField(<span class="string">&#x27;机构描述&#x27;</span>)</span><br><span class="line">    click_nums = models.IntegerField(<span class="string">&#x27;点击数&#x27;</span>,default=<span class="number">0</span>)</span><br><span class="line">    fav_nums = models.IntegerField(<span class="string">&#x27;收藏数&#x27;</span>,default=<span class="number">0</span>)</span><br><span class="line">    image = models.ImageField(<span class="string">&#x27;封面图&#x27;</span>,upload_to=<span class="string">&#x27;org/%Y%m&#x27;</span>,max_length=<span class="number">100</span>)</span><br><span class="line">    address = models.CharField(<span class="string">&#x27;机构地址&#x27;</span>,max_length=<span class="number">150</span>,)</span><br><span class="line">city = models.ForeignKey(CityDict,\</span><br><span class="line">verbose_name=<span class="string">&#x27;所在城市&#x27;</span>,on_delete=models.CASCADE)</span><br><span class="line">    add_time = models.DateTimeField(default=datetime.now)</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        verbose_name = <span class="string">&#x27;课程机构&#x27;</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br></pre></td></tr></table></figure><p>3.4 Operation 操作<br>根据上述需求的分析,操作模型的设计如下表3.4所示：<br>表3.4 operation需求表单</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">表名字字段名字段类型默认值(default)备注</span><br><span class="line">UserCourse</span><br><span class="line">用户学习的课程userCharField用户</span><br><span class="line">courseCharField课程</span><br><span class="line">add_timeDateTimeFielddatetime.now添加时间</span><br><span class="line">IS_FINISHED((0,&quot;未完成&quot;),</span><br><span class="line">(1,&quot;已完成&quot;))</span><br><span class="line">is_finishedIntegerField0</span><br></pre></td></tr></table></figure><p>给出operation/models.py代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserCourse</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">user = models.ForeignKey(UserProfile,\</span><br><span class="line">verbose_name=<span class="string">&#x27;用户&#x27;</span>,on_delete=models.CASCADE)</span><br><span class="line">course = models.ForeignKey(Course,verbose_name=<span class="string">&#x27;课程&#x27;</span>,\</span><br><span class="line">on_delete=models.CASCADE)</span><br><span class="line">    add_time = models.DateTimeField(<span class="string">&#x27;添加时间&#x27;</span>, default=datetime.now)</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        verbose_name = <span class="string">&#x27;用户课程&#x27;</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br></pre></td></tr></table></figure><h1 id="4-Xadmin后台管理"><a href="#4-Xadmin后台管理" class="headerlink" title="4.Xadmin后台管理"></a>4.Xadmin后台管理</h1><h2 id="4-1-Xadmin的安装和设置"><a href="#4-1-Xadmin的安装和设置" class="headerlink" title="4.1 Xadmin的安装和设置"></a>4.1 Xadmin的安装和设置</h2><p>可以访问github开源仓库获取到源码进行安装,首先要获得django2.0的zip文件,放置到已经安装好pip工具的安装目录下,其源码访问链接为：<br><a href="https://github.com/sshwsfc/xadmin/tree/django2">https://github.com/sshwsfc/xadmin/tree/django2</a><br>获取到源码后,解压到pip安装目录,然后运行下面命令安装：<br>pip install xadmin-django2<br>如果无法访问github开源仓库,可以更换安装源,比如说使用豆瓣源,命令如下：<br>pip install -i <a href="https://pypi.douban.com/simple">https://pypi.douban.com/simple</a> xadmin-django2<br>安装完成后,同时也安装了很多依赖的包。<br>以下进行Xadmin的设置,进行简单分布操作如下：<br>（1）新建Python Package “extra_apps”,把源码xadmin文件夹放到extra_apps文件夹下面,此时目录结构如下：<br>MxOnline&gt;extra_apps&gt;xadmin&gt;<em>init</em>.py<br>（2）把extra_apps右键mark为Source Root并在settings中加入：<br>sys.path.insert(0,os.path.join(BASE_DIR, ‘extra_apps’))<br>（3）因为我们用源码的xadmin,所以要卸载之前安装的：<br>pip uninstall xadmin<br>（4）配置路由,把admin改成xadmin,代码如下所示：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># urls.py</span></span><br><span class="line"><span class="keyword">from</span> django.urls <span class="keyword">import</span> path</span><br><span class="line"><span class="keyword">import</span> xadmin</span><br><span class="line">urlpatterns = [</span><br><span class="line">    path(<span class="string">&#x27;xadmin/&#x27;</span>, xadmin.site.urls),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>（5）注册app,把下面两个app注册到settings.py的INSTALLED_APPS中配置如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#39;xadmin&#39;,</span><br><span class="line">&#39;crispy_forms&#39;</span><br></pre></td></tr></table></figure><p>（6）重新生成数据库,运行如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">python manage.py makemigrations</span><br><span class="line">python manage.py migrate</span><br></pre></td></tr></table></figure><p>（7）设置成中文,在加载的框架中修改如下内容为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">LANGUAGE_CODE &#x3D; &#39;zh-hans&#39;</span><br><span class="line">TIME_ZONE &#x3D; &#39;Asia&#x2F;Shanghai&#39;</span><br><span class="line">USE_I18N &#x3D; True</span><br><span class="line">USE_L10N &#x3D; True</span><br><span class="line">USE_TZ &#x3D; False</span><br></pre></td></tr></table></figure><p>（8）创建一个管理员用户,并且启动框架就能进入管理界面,操作命令和管理界面如图4.1所示：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">python manage.py createsuperuser</span><br><span class="line">python manage.py runserver</span><br></pre></td></tr></table></figure><p>图4.1 框架后台管理界面</p><h2 id="4-2-模块添加和注册"><a href="#4-2-模块添加和注册" class="headerlink" title="4.2 模块添加和注册"></a>4.2 模块添加和注册</h2><p>首先在在users下面创建adminx.py,代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># users/adminx.py</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> xadmin</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> .models <span class="keyword">import</span> EmailVerifyRecord</span><br><span class="line"><span class="comment">#xadmin中这里是继承object,不再是继承admin</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">EmailVerifyRecordAdmin</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">xadmin.site.register(EmailVerifyRecord,EmailVerifyRecordAdmin)</span><br></pre></td></tr></table></figure><p>创建以上管理后,开始进行根据上节django模型设计的分析内容,开始进行各种功能的创建和注册,以达到最初设计的要求。由于这部分内容比较庞大,在报告中不能一一进行注册的描述占用篇幅,因此只是对部分代表性的功能模块进行注册叙述。</p><p>比如将users中Banner也注册进去,则注册代码如下所示：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BannerAdmin</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    list_display = [<span class="string">&#x27;title&#x27;</span>, <span class="string">&#x27;image&#x27;</span>, <span class="string">&#x27;url&#x27;</span>,<span class="string">&#x27;index&#x27;</span>, <span class="string">&#x27;add_time&#x27;</span>]</span><br><span class="line">    search_fields = [<span class="string">&#x27;title&#x27;</span>, <span class="string">&#x27;image&#x27;</span>, <span class="string">&#x27;url&#x27;</span>,<span class="string">&#x27;index&#x27;</span>]</span><br><span class="line">    list_filter = [<span class="string">&#x27;title&#x27;</span>, <span class="string">&#x27;image&#x27;</span>, <span class="string">&#x27;url&#x27;</span>,<span class="string">&#x27;index&#x27;</span>, <span class="string">&#x27;add_time&#x27;</span>]</span><br><span class="line"></span><br><span class="line">xadmin.site.register(Banner,BannerAdmin)</span><br></pre></td></tr></table></figure><p>比如说将course注册进去,则注册代码如下所示：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"># course&#x2F;adminx.py</span><br><span class="line">import xadmin</span><br><span class="line">from .models import Course, Lesson, Video, CourseResource</span><br><span class="line"></span><br><span class="line">class CourseAdmin(object):#课程</span><br><span class="line">    list_display &#x3D; [ &#39;name&#39;,&#39;desc&#39;,&#39;detail&#39;,\</span><br><span class="line">&#39;degree&#39;,&#39;learn_times&#39;,&#39;students&#39;]</span><br><span class="line">    search_fields &#x3D; [&#39;name&#39;, &#39;desc&#39;, &#39;detail&#39;,\</span><br><span class="line"> &#39;degree&#39;, &#39;students&#39;]</span><br><span class="line">    list_filter &#x3D; [ &#39;name&#39;,&#39;desc&#39;,&#39;detail&#39;,&#39;degree&#39;,\</span><br><span class="line">&#39;learn_times&#39;,&#39;students&#39;]</span><br><span class="line">class LessonAdmin(object): #章节</span><br><span class="line">    list_display &#x3D; [&#39;course&#39;, &#39;name&#39;, &#39;add_time&#39;]</span><br><span class="line">    search_fields &#x3D; [&#39;course&#39;, &#39;name&#39;]</span><br><span class="line">    #这里course__name是根据课程名称过滤</span><br><span class="line">    list_filter &#x3D; [&#39;course__name&#39;, &#39;name&#39;, &#39;add_time&#39;]</span><br><span class="line">class VideoAdmin(object):#视频</span><br><span class="line">    list_display &#x3D; [&#39;lesson&#39;, &#39;name&#39;, &#39;add_time&#39;]</span><br><span class="line">    search_fields &#x3D; [&#39;lesson&#39;, &#39;name&#39;]</span><br><span class="line">    list_filter &#x3D; [&#39;lesson&#39;, &#39;name&#39;, &#39;add_time&#39;]</span><br><span class="line">class CourseResourceAdmin(object):#课程资源</span><br><span class="line">    list_display &#x3D; [&#39;course&#39;, &#39;name&#39;, &#39;download&#39;, &#39;add_time&#39;]</span><br><span class="line">    search_fields &#x3D; [&#39;course&#39;, &#39;name&#39;, &#39;download&#39;]</span><br><span class="line">    list_filter &#x3D; [&#39;course__name&#39;, &#39;name&#39;, &#39;download&#39;, &#39;add_time&#39;]</span><br></pre></td></tr></table></figure><p>将管理器与model进行注册关联</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">xadmin.site.register(Course, CourseAdmin)</span><br><span class="line">xadmin.site.register(Lesson, LessonAdmin)</span><br><span class="line">xadmin.site.register(Video, VideoAdmin)</span><br><span class="line">xadmin.site.register(CourseResource, CourseResourceAdmin)</span><br></pre></td></tr></table></figure><p>将django模型和第二节模块功能设计的内容全部按照规则注册关联后,则整个项目初步完成,只需要进行后台管理操作进行增添删改,补充内容,再进行整体网站的安全检测就可以上线了,设计完成后的空白后台<br>如下图4.2所示：</p><p>图4.2 注册完全后的空白后台</p><h1 id="5．内容填充"><a href="#5．内容填充" class="headerlink" title="5．内容填充"></a>5．内容填充</h1><p>进行以上设计后,整体建站的设计基本完成,只需要将要发布的内容在管理后台进行添加发布即可,可对整个网站进行管理。参考mooc网的网上课程的模式,收集一些课程信息在管理后台进行发布,继续打造整个网站,最终结果如下图5.1所示：</p><p>图5.1 发布课程</p><h1 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h1><p>[1]  Django项目实例精解（第2版）作者:[美]安东尼奥米勒 清华大学出版社<br>[2]  Python Web开发实战 作者:董伟明著 出版社:电子工业出版社<br>[3]  MySQL 5.7从入门到精通（视频教学版）（第2版）张工厂 清华大学出版社<br>[4]  Python Django Web典型模块开发实战 作者:寇雪松 出版社:机械工业出版社 </p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>基于autohotkey的colmak布局配置</title>
      <link href="comic/autohotkey_colmak/"/>
      <url>comic/autohotkey_colmak/</url>
      
        <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>大部分同学使用的键盘布局都是QWERTY布局</p><p>而科学研究表明,可能这个设计不是最高效率的布局,甚至的有意为了降低打字的效率而研究的，那么当初为什么要这么设计呢？<br>关于键盘布局历史故事的详细内容，可以参考：<a href="https://www.zhihu.com/question/20121876/answer/129017959">知乎:键盘布局有哪些种？各种布局的设计出发点是什么？</a></p><p><strong>今天小编给大家介绍另一种布局</strong></p><h2 id="colemak布局"><a href="#colemak布局" class="headerlink" title="colemak布局"></a>colemak布局</h2><p><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210315154311.jpg"></p><p>这种键盘布局,根据热力图显示,我们打字中经常使用的按键（比如元音字母a,o,e,i,u）都会被设计在键盘的中间的一排中,这样可以减少我们在打字的过程中的手指的移动,打字的效率自然就会提高</p><p><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210315154312.jpg"></p><p>切换这种布局的方式有很多，经过小编汗水亲测以及对比，autohotkey是其中最好的解决方案，因为他是通过脚本进行按键的替换，所以在使用的时候你不需要局限于输入法，你可以使用colmak输入英文，也可以使用它来输入中文（拼音输入）。<br>万事开头难，你一开始使用他一定会不适应的，但是只要你坚持打到3个星期，我相信，这个时候你的打字速度足够满足正常的输入需求了。</p><h2 id="autohotkey介绍"><a href="#autohotkey介绍" class="headerlink" title="autohotkey介绍"></a>autohotkey介绍</h2><p>AutoHotkey 是一个自动化软件工具，通过热键、热字串或设定的条件自动执行重复性工作。首页 发现 等你来答 登录 加入知乎 AutoHotkey AutoHotkey 是一个自动化软件工具，通过热键、热字串或设定的条件自动执行重复性工作 .</p><p>更多详细信息也可以参考<a href="https://www.autohotkey.com/">autohotkey官网</a> 或者 <a href="http://ahkcn.sourceforge.net/docs/AutoHotkey.htm">中文文档</a></p><h2 id="autohotkey安装"><a href="#autohotkey安装" class="headerlink" title="autohotkey安装"></a>autohotkey安装</h2><p>在使用autohotkey之前,我们需要进行下载安装</p><p><a href="https://autohotkey.com/download/ahk-install.exe">https://autohotkey.com/download/ahk-install.exe</a></p><p>安装后会有文档提示,这里我们可以看<a href="https://wyagd001.github.io/zh-cn/docs/Tutorial.htm#s11">在线的文档</a>,因为这里面有指定语言,可以翻译成中文来阅读</p><h2 id="如何创建一个脚本"><a href="#如何创建一个脚本" class="headerlink" title="如何创建一个脚本"></a>如何创建一个脚本</h2><p>这里面有很多的语法,我们需要实现的功能是创建一个替换键盘位置的脚本,所以不需要过多的了解这个语法和基本数据类型以及流程控制和函数中</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">右键点桌面空白处.</span><br><span class="line">点击&quot;新建&quot;菜单.</span><br><span class="line">点击里面的&quot;AutoHotkey Script&quot;新建一个脚本.</span><br><span class="line">给脚本命名. 备注: 文件名必须带 .ahk 后缀, 例如 MyScript.ahk</span><br><span class="line">找到刚刚新建的脚本并右键点击它.</span><br><span class="line">点击&quot;Edit Script&quot;.</span><br><span class="line">一个新窗口被弹出, 也许是记事本. 如果是这样就成功了!</span><br><span class="line">现在你已经创建了一个脚本, 我们需要加点内容到脚本中. 如果需要用到内置命令, 函数和变量, 请查看第 5 节.</span><br><span class="line"></span><br><span class="line">这是一个使用 Send 命令创建的一个包含热键的简单脚本, 当你按下热键后, 它会向窗口发送一段文字.</span><br><span class="line"></span><br><span class="line">^j::</span><br><span class="line">Send, My First Script</span><br><span class="line">Return</span><br><span class="line">S↓</span><br><span class="line">稍后我们将进行更深入的研究. 在此之前, 我们先解释一下上面的代码:</span><br><span class="line"></span><br><span class="line">第一行: ^j:: 是热键. ^ 代表 Ctrl, j 是字母 J. 任何在 :: 左边 的字符表示您需要按下的热键.</span><br><span class="line">第二行: Send, My First Script 表示如何发送按键. Send 是命令, 任何在逗号(,) 之后的内容将会被键入.</span><br><span class="line">第三行: Return. Return 将会成为你最好的朋友. 它将停止执行之后的代码. 当你的脚本包含越来越多的东西时, 使用 Return 会避免很多问题.</span><br><span class="line">保存文件.</span><br><span class="line">双击桌面上的文件来运行它, 打开记事本或者其他可以输入文字的地方然后按下 Ctrl 和 J.</span><br><span class="line">太好了! 你的第一个脚本完成了. 给自己一些奖励, 然后返回阅读本教程的其余部分.</span><br></pre></td></tr></table></figure><h2 id="autohotkey使用"><a href="#autohotkey使用" class="headerlink" title="autohotkey使用"></a>autohotkey使用</h2><p>其实autohotkey的功能十分的强大,我们这次只是会使用其中的最最基础的功能</p><p>我写的脚本代码如下</p><figure class="highlight ahk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">* author:@victorfegming</span></span><br><span class="line"><span class="comment">* address:gitee.com/victorfengming</span></span><br><span class="line"><span class="comment">* 项目下载:https://gitee.com/victorfengming/colmak_autohotkey</span></span><br><span class="line"><span class="comment">* 博客地址:https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">;先看效果:替换后的布局</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> `~  1 2 3 4 5 6 7 8 9 0 - = backsp</span></span><br><span class="line"><span class="comment">Tab   Q W F P G J L U Y ; [ ]  \</span></span><br><span class="line"><span class="comment">Back   A R S T D H N E I O &quot; Enterr</span></span><br><span class="line"><span class="comment">LShift  Z X C V B K M , . / RShiftt</span></span><br><span class="line"><span class="comment">Ctrl Win Alt  Space Alt Menu Fn Ctrl</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">   l u y</span></span><br><span class="line"><span class="comment"> h n e i o &#x27;</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">   up↑down</span></span><br><span class="line"><span class="comment">&lt;&lt; ← ↓ → &gt;&gt; del</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">;colemak的对应QWERTY键位</span></span><br><span class="line"><span class="title">e::</span>f</span><br><span class="line"><span class="title">r::</span>p</span><br><span class="line"><span class="title">t::</span>g</span><br><span class="line"><span class="title">y::</span>j</span><br><span class="line"><span class="title">u::</span>l</span><br><span class="line"><span class="title">i::</span>u</span><br><span class="line"><span class="title">o::</span>y</span><br><span class="line"><span class="title">p::</span><span class="comment">;</span></span><br><span class="line"><span class="title">s::</span>r</span><br><span class="line"><span class="title">d::</span>s</span><br><span class="line"><span class="title">f::</span>t</span><br><span class="line"><span class="title">g::</span>d</span><br><span class="line"><span class="title">j::</span>n</span><br><span class="line"><span class="title">k::</span>e</span><br><span class="line"><span class="title">l::</span>i</span><br><span class="line">`;::o</span><br><span class="line"><span class="title">n::</span>k</span><br><span class="line"><span class="comment">; 这里的替换不会影响组合的修饰符</span></span><br><span class="line"><span class="comment">; 比如现在按Ctrl+F就是Ctrl+F,不会是原来的Ctrl+E</span></span><br><span class="line"></span><br><span class="line"><span class="comment">;这里是替换大写和退格</span></span><br><span class="line"><span class="title">CapsLock::</span>BackSpace</span><br><span class="line"><span class="comment">;大写切换不会经常用,平时用shift</span></span><br><span class="line"><span class="title">LShift &amp; CapsLock::</span>CapsLock</span><br><span class="line"><span class="comment">;强烈建议这里换成删除,因为删除的按键距离主键盘过远,影响打字效率</span></span><br><span class="line"></span><br><span class="line"><span class="comment">;Alt 的 方向组合</span></span><br><span class="line"><span class="title">&lt;!i::</span>send &#123;up&#125;</span><br><span class="line"><span class="title">&lt;!k::</span>send &#123;Down&#125;</span><br><span class="line"><span class="title">&lt;!j::</span>send &#123;Left&#125;</span><br><span class="line"><span class="title">&lt;!l::</span>send &#123;Right&#125;</span><br><span class="line"><span class="title">&lt;!&#x27;::</span>send &#123;Del&#125;</span><br><span class="line"><span class="comment">;&lt;h-o&gt; =&gt;&gt; Home End</span></span><br><span class="line"><span class="title">&lt;!h::</span>send &#123;Home&#125;</span><br><span class="line">&lt;!`;::send &#123;End&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">;Alt shift组合方向键</span></span><br><span class="line"><span class="title">&lt;+&lt;!i::</span>send &#123;Shift down&#125;&#123;up&#125;</span><br><span class="line"><span class="title">&lt;+&lt;!k::</span>send &#123;Shift down&#125;&#123;Down&#125;</span><br><span class="line"><span class="title">&lt;+&lt;!j::</span>send &#123;Shift down&#125;&#123;Left&#125;</span><br><span class="line"><span class="title">&lt;+&lt;!l::</span>send &#123;Shift down&#125;&#123;Right&#125;</span><br><span class="line"><span class="title">&lt;+&lt;!h::</span>send &#123;Shift down&#125;&#123;Home&#125;</span><br><span class="line">&lt;+&lt;!`;::send &#123;Shift down&#125;&#123;End&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">;Alt ctrl组合方向键</span></span><br><span class="line"><span class="title">&lt;^&lt;!i::</span>send &#123;Ctrl down&#125;&#123;up&#125;</span><br><span class="line"><span class="title">&lt;^&lt;!k::</span>send &#123;Ctrl down&#125;&#123;Down&#125;</span><br><span class="line"><span class="title">&lt;^&lt;!j::</span>send &#123;Ctrl down&#125;&#123;Left&#125;</span><br><span class="line"><span class="title">&lt;^&lt;!l::</span>send &#123;Ctrl down&#125;&#123;Right&#125;</span><br><span class="line"><span class="title">&lt;^&lt;!h::</span>send &#123;Ctrl down&#125;&#123;Home&#125;</span><br><span class="line">&lt;^&lt;!`;::send &#123;Ctrl down&#125;&#123;End&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">;Alt Ctrl Shift 组合方向键</span></span><br><span class="line"><span class="title">&lt;^&lt;+&lt;!i::</span>send &#123;Ctrl down&#125;&#123;Shift down&#125;&#123;up&#125;</span><br><span class="line"><span class="title">&lt;^&lt;+&lt;!k::</span>send &#123;Ctrl down&#125;&#123;Shift down&#125;&#123;Down&#125;</span><br><span class="line"><span class="title">&lt;^&lt;+&lt;!j::</span>send &#123;Ctrl down&#125;&#123;Shift down&#125;&#123;Left&#125;</span><br><span class="line"><span class="title">&lt;^&lt;+&lt;!l::</span>send &#123;Ctrl down&#125;&#123;Shift down&#125;&#123;Right&#125;</span><br><span class="line"><span class="title">&lt;^&lt;+&lt;!h::</span>send &#123;Ctrl down&#125;&#123;Shift down&#125;&#123;Home&#125;</span><br><span class="line">&lt;^&lt;+&lt;!`;::send &#123;Ctrl down&#125;&#123;Shift down&#125;&#123;End&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">;Alt + ly page↑page↓</span></span><br><span class="line"><span class="title">&lt;!u::</span>send &#123;PgUp&#125;</span><br><span class="line"><span class="title">&lt;!o::</span>send &#123;PgDn&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">;禁止方向键，提醒使用主键盘</span></span><br><span class="line"><span class="title">up::</span><span class="keyword">return</span></span><br><span class="line"><span class="title">Down::</span><span class="keyword">return</span></span><br><span class="line"><span class="title">Left::</span><span class="keyword">return</span></span><br><span class="line"><span class="title">Right::</span><span class="keyword">return</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">相关知识点:</span></span><br><span class="line"><span class="comment">- 原文地址:http://ahkcn.sourceforge.net/docs/AutoHotkey.htm</span></span><br><span class="line"><span class="comment">- 映射表地址:http://ahkcn.sourceforge.net/docs/KeyList.htm</span></span><br><span class="line"><span class="comment">- :: 表示映射</span></span><br><span class="line"><span class="comment">- send 发送组合键</span></span><br><span class="line"><span class="comment">- `符号用来转义;分号</span></span><br><span class="line"><span class="comment">- 修饰符 Ctrl Alt Shift 对应 ^+!</span></span><br><span class="line"><span class="comment">- down表示按下的状态</span></span><br><span class="line"><span class="comment">- &amp;表示组合键</span></span><br><span class="line"><span class="comment">- &lt;表示只有左边的修饰符生效</span></span><br><span class="line"><span class="comment">- return 啥也不干</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>然后将脚本文件保存成Unicode编码,在桌面双击即可执行脚本</p><p>执行过后,你会发现,你的键位立即生效了</p><p>如果你想停止,或者暂停,也可以在window的任务栏中,找到对应的图标</p><p>右击的菜单中进行相应的设置</p><p>如果你想打包成可执行文件,发给没有安装autohotkey的计算机中亦可以使用</p><p>操作方式很easy,在脚本文件中右击,选择Compile Script,即可在当前文件夹,生成一个与脚本文件同名的exe可执行文件</p><h2 id="键盘键帽"><a href="#键盘键帽" class="headerlink" title="键盘键帽"></a>键盘键帽</h2><p>如果你是 机械键盘 , 在练习初期可以像这样把键帽 重新排列成这种布局, 这样可以让你快速 熟悉</p><p><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210315153718.jpg"></p><h2 id="编辑器"><a href="#编辑器" class="headerlink" title="编辑器"></a>编辑器</h2><p>支持autohotkey语法高亮的编辑器很多,小编使用的是sublime</p><p>关于它的插件的安装,可以参考<a href="https://packagecontrol.io/packages/AutoHotkey">这里</a> </p><h2 id="项目源代码地址"><a href="#项目源代码地址" class="headerlink" title="项目源代码地址"></a>项目源代码地址</h2><p>码云：<a href="https://gitee.com/victorfengming/colmak_autohotkey">https://gitee.com/victorfengming/colmak_autohotkey</a></p><p>感觉有帮助的伙伴可以给小编<code>star</code>一下</p><h2 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h2><p>放一张图</p><p><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210315154310.jpg"><br><img src= "/img/loading.gif" data-lazy-src="%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210315153756.jpg"></p>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> solution </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>基于django和vue的xdh官网设计</title>
      <link href="python/Django/django-vue-xdh/"/>
      <url>python/Django/django-vue-xdh/</url>
      
        <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>本项目是使用三段分离的设计</p><h2 id="前台"><a href="#前台" class="headerlink" title="前台"></a>前台</h2><p>使用materialize框架搭建的前台页面,后端使用的django写的接口</p><h2 id="后台"><a href="#后台" class="headerlink" title="后台"></a>后台</h2><p>使用Amazon UI 模板搭建的界面,管理各个部分的内容</p><h2 id="项目环境"><a href="#项目环境" class="headerlink" title="项目环境"></a>项目环境</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">python3.7.2</span><br><span class="line">django2.2.9</span><br><span class="line">vue </span><br><span class="line">axios</span><br><span class="line">jQuery</span><br><span class="line">materialize</span><br><span class="line">mysql</span><br></pre></td></tr></table></figure><h1 id="摘-要"><a href="#摘-要" class="headerlink" title="摘 要"></a>摘 要</h1><p>本设计采用前后端分离的设计模式,前端通过vue的axios发送ajax请求来调用后端接口,实现页面的展示,后端使用Python中的django框架来访问数据库,并返回json数据。django是一个完整的开源web开源框架,使用起来能够快速的搭建你想要的网站。本设计中后台管理模板采用amazeUI页面的样式实现。数据库部分采用开源的mysql数据库,由于django操作数据库很方便,所以我们只需要关心框架中的models类的设计即可,只需要关心视图逻辑,后台管理系统即可实现基本的增删改查功能。  </p><p>关键词：Python;Vue;Django;ajax;Mysql;</p><h1 id="1-基础环境的简介"><a href="#1-基础环境的简介" class="headerlink" title="1.    基础环境的简介"></a>1.    基础环境的简介</h1><h2 id="1-1-Python介绍。"><a href="#1-1-Python介绍。" class="headerlink" title="1.1  Python介绍。"></a>1.1  Python介绍。</h2><p>Python是一种跨平台的计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。<br>Python的设计哲学是“优雅”、“明确”、“简单”。因此,Perl语言中“总是有多种方法来做同一件事”的理念在Python开发者中通常是难以忍受的。Python开发者的哲学是“用一种方法,最好是只有一种方法来做一件事”。在设计Python语言时,如果面临多种选择,Python开发者一般会拒绝花俏的语法,而选择明确的没有或者很少有歧义的语法。由于这种设计观念的差异,Python源代码通常被认为比Perl具备更好的可读性,并且能够支撑大规模的软件开发。这些准则被称为Python格言。在Python解释器内运行import this可以获得完整的列表。Python是完全面向对象的语言。函数、模块、数字、字符串都是对象。并且完全支持继承、重载、派生、多继承,有益于增强源代码的复用性。 </p><h2 id="1-2-Python-特点"><a href="#1-2-Python-特点" class="headerlink" title="1.2  Python 特点"></a>1.2  Python 特点</h2><h3 id="1-易于学习"><a href="#1-易于学习" class="headerlink" title="1.易于学习"></a>1.易于学习</h3><p>Python有相对较少的关键字,结构简单,学习起来更加简单。</p><h3 id="2-易于阅读"><a href="#2-易于阅读" class="headerlink" title="2.易于阅读"></a>2.易于阅读</h3><p>Python代码定义的更清晰。</p><h3 id="3-易于维护"><a href="#3-易于维护" class="headerlink" title="3.易于维护"></a>3.易于维护</h3><p>Python的成功在于它的源代码是相当容易维护的。</p><h3 id="4-一个广泛的标准库"><a href="#4-一个广泛的标准库" class="headerlink" title="4.一个广泛的标准库"></a>4.一个广泛的标准库</h3><p>Python的最大的优势之一是丰富的库,跨平台的,兼容很好。</p><h3 id="5-互动模式"><a href="#5-互动模式" class="headerlink" title="5.互动模式"></a>5.互动模式</h3><p>您可以从终端输入执行代码并获得结果的语言,互动的测试和调试代码片断。</p><h3 id="6-可移植"><a href="#6-可移植" class="headerlink" title="6.可移植"></a>6.可移植</h3><p>基于其开放源代码的特性,Python已经被移植（也就是使其工作）到许多平台。</p><h3 id="7-可扩展"><a href="#7-可扩展" class="headerlink" title="7.可扩展"></a>7.可扩展</h3><p>如果你需要一段运行很快的关键代码,或者是想要编写一些不愿开放的算法,你可以使用C或C++完成那部分程序,然后从你的Python程序中调用。</p><h3 id="8-数据库"><a href="#8-数据库" class="headerlink" title="8.数据库"></a>8.数据库</h3><p>Python提供所有主要的商业数据库的接口。</p><h3 id="9-GUI编程"><a href="#9-GUI编程" class="headerlink" title="9.GUI编程"></a>9.GUI编程</h3><p>Python支持GUI可以创建和移植到许多系统调用。</p><h3 id="10-可嵌入"><a href="#10-可嵌入" class="headerlink" title="10.可嵌入"></a>10.可嵌入</h3><p> 你可以将Python嵌入到C/C++程序,让你的程序的用户获得”脚本化”的能力。</p><h2 id="1-3-Django介绍"><a href="#1-3-Django介绍" class="headerlink" title="1.3  Django介绍"></a>1.3  Django介绍</h2><p>Django 是一个高级的 Python 网络框架,可以快速开发安全和可维护的网站。由经验丰富的开发者构建,Django负责处理网站开发中麻烦的部分,因此你可以专注于编写应用程序,而无需重新开发。<br>它是免费和开源的,有活跃繁荣的社区,丰富的文档,以及很多免费和付费的解决方案。</p><h3 id="1-3-1-完备性"><a href="#1-3-1-完备性" class="headerlink" title="1.3.1 完备性"></a>1.3.1 完备性</h3><p>Django遵循“功能完备”的理念,提供开发人员可能想要“开箱即用”的几乎所有功能。因为你需要的一切都是一个”产品“的一部分,它们都可以无缝结合在一起,遵循一致性设计原则,并且具有广泛和最新的文档.</p><h3 id="1-3-2-通用性"><a href="#1-3-2-通用性" class="headerlink" title="1.3.2 通用性"></a>1.3.2 通用性</h3><p>Django 可以（并已经）用于构建几乎任何类型的网站—从内容管理系统和维基,到社交网络和新闻网站。它可以与任何客户端框架一起工作,并且可以提供几乎任何格式（包括 HTML,Rss源,JSON,XML等）的内容。你正在阅读的网站就是基于Django。</p><p>在内部,尽管它为几乎所有可能需要的功能（例如几个流行的数据库,模版引擎等）提供了选择,但是如果需要,它也可以扩展到使用其他组件。</p><h3 id="1-3-3-安全性"><a href="#1-3-3-安全性" class="headerlink" title="1.3.3 安全性"></a>1.3.3 安全性</h3><p>Django 帮助开发人员通过提供一个被设计为“做正确的事情”来自动保护网站的框架来避免许多常见的安全错误。例如,Django提供了一种安全的方式来管理用户账户和密码,避免了常见的错误,比如将session放在cookie中这种易受攻击的做法（取而代之的是cookies只包含一个密钥,实际数据存储在数据库中）或直接存储密码而不是密码哈希。</p><h3 id="1-3-4-可扩展"><a href="#1-3-4-可扩展" class="headerlink" title="1.3.4 可扩展"></a>1.3.4 可扩展</h3><p>Django 使用基于组件的 “无共享” 架构 (架构的每一部分独立于其他架构,因此可以根据需要进行替换或更改). 在不用部分之间有明确的分隔意味着它可以通过在任何级别添加硬件来扩展服务：缓存服务器,数据库服务器或应用程序服务器。一些最繁忙的网站已经成功地缩放了Django,以满足他们的需求（例如Instagram和Disqus,仅举两个例子,可自行添加）。</p><h3 id="1-3-5-可维护性"><a href="#1-3-5-可维护性" class="headerlink" title="1.3.5 可维护性"></a>1.3.5 可维护性</h3><p>Django 代码编写是遵照设计原则和模式,鼓励创建可维护和可重复使用的代码。特别是它使用了不要重复自己（DRY）原则,所以没有不必要的重复,减少了代码的数量。Django还将相关功能分组到可重用的“应用程序”中,并且在较低级别将相关代码分组或模块（ 模型视图控制器 (MVC) 模式).</p><h3 id="1-3-6-灵活性"><a href="#1-3-6-灵活性" class="headerlink" title="1.3.6 灵活性"></a>1.3.6 灵活性</h3><p>Django 是用Python编写的,它在许多平台上运行。这意味着你不受任务特定的服务器平台的限制,并且可以在许多种类的Linux,Windows和Mac OsX 上运行应用程序。此外,Django得到许多网络托管提供商的好评,他们经常提供特定的基础设施和托管Django网站的文档。</p><h2 id="1-4-Mysql介绍"><a href="#1-4-Mysql介绍" class="headerlink" title="1.4  Mysql介绍"></a>1.4  Mysql介绍</h2><p>MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。<br>MySQL 使用的 SQL 语言是用于访问数据库的最常用的标准化语言。<br>由于 MySQL 数据库体积小、速度快、总体拥有成本低、开放源代码,其有着广泛的应用,一般中小型网站的开发都选择 MySQL 作为网站数据库。由于其社区版的性能卓越,因此搭配 PHP 和 Apache 服务器可组成良好的开发环境。</p><h1 id="2-需求分析"><a href="#2-需求分析" class="headerlink" title="2.    需求分析"></a>2.    需求分析</h1><p>建站包括前台功能系统和后台管理系统两大系统组成,分别由不同能力的人 员实现,而前台功能系统是属于 UI 设计类的,后台管理系统是程序类的,因此 本设计选择进行后台管理系统设计。 由于本设计是后台管理系统,主要功能是对前台展示的页面进行增删改查的操作。<br>本站主要的功能是作为信息的展示和宣传,大体上分为4个页面：首页,课程页,教学特色页和学员风采页。主要功能如下图所示：</p><p>图2.1 XDH官网需求分析图</p><h2 id="2-1-首页"><a href="#2-1-首页" class="headerlink" title="2.1 首页"></a>2.1 首页</h2><p>首页主要分为以下几部分：<br>（1）轮播图<br>（2）兄弟会介绍<br>（3）兄弟会与传统就业班区别<br>（4）师资力量<br>（5）就业喜报<br>（6）学科介绍</p><h2 id="2-2-课程介绍"><a href="#2-2-课程介绍" class="headerlink" title="2.2 课程介绍"></a>2.2 课程介绍</h2><pre><code>（1）培训课程,具体学科介绍（2）兄弟会具体学科及分级介绍（3）兄弟会解决了什么问题（4）重点突出兄弟会课程体系与传统培训体系的不同 （5）学习的苦VS生活的苦（不吃学习的苦就要吃生活的苦）</code></pre><h2 id="2-3-教学特色"><a href="#2-3-教学特色" class="headerlink" title="2.3 教学特色"></a>2.3 教学特色</h2><pre><code>（1）办学理念-具有真实交付能力的程序员（2）项目驱动式学习-每阶段都有可锻炼的项目（3）企业级项目经理指导（4）真实的企业级商业项目全程开发（5）学习经验分享（6）企业文化培训（培养身心健康的程序员）</code></pre><h2 id="2-4-学员风采"><a href="#2-4-学员风采" class="headerlink" title="2.4 学员风采"></a>2.4 学员风采</h2><pre><code>（1）学员采访视频（2）学员感言（3）个人博客（4）团建活动（5）我们的作品</code></pre><h1 id="3-Django模型model类的设计"><a href="#3-Django模型model类的设计" class="headerlink" title="3.    Django模型model类的设计"></a>3.    Django模型model类的设计</h1><p>模型设计是整个项目的核心部分,直接决定了项目后续的可行性,这里我们分为两个 app 来进行设计,分别为api和bgapi,一个作为前台的接口,一个是进行后台管理的接口。</p><h2 id="3-1-导入所需模块"><a href="#3-1-导入所需模块" class="headerlink" title="3.1 导入所需模块"></a>3.1 导入所需模块</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"><span class="keyword">from</span> django.utils <span class="keyword">import</span> timezone</span><br></pre></td></tr></table></figure><h2 id="3-2-所有轮播图"><a href="#3-2-所有轮播图" class="headerlink" title="3.2 所有轮播图"></a>3.2 所有轮播图</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Banner</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">img = models.TextField()</span><br><span class="line">page = models.CharField(max_length=<span class="number">20</span>)</span><br><span class="line">link = models.CharField(max_length=<span class="number">100</span>)</span><br><span class="line">is_del = models.IntegerField(default=<span class="number">0</span>)</span><br><span class="line">join_date = models.DateTimeField(default=timezone.now)</span><br></pre></td></tr></table></figure><h2 id="3-3-工作信息表"><a href="#3-3-工作信息表" class="headerlink" title="3.3 工作信息表"></a>3.3 工作信息表</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">JobInfo</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">major = models.CharField(max_length=<span class="number">50</span>,default=<span class="string">&quot;&quot;</span>)</span><br><span class="line">    <span class="comment"># 专业major 主修,专业 (专指大学)</span></span><br><span class="line">school = models.CharField(max_length=<span class="number">50</span>)</span><br><span class="line">name = models.CharField(max_length=<span class="number">20</span>)</span><br><span class="line">title = models.CharField(max_length=<span class="number">50</span>)</span><br><span class="line">img = models.CharField(max_length=<span class="number">200</span>)</span><br><span class="line">salary = models.CharField(max_length=<span class="number">20</span>)</span><br><span class="line">date = models.DateField()</span><br><span class="line">is_del = models.IntegerField(default=<span class="number">0</span>)</span><br><span class="line">join_date = models.DateTimeField(default=timezone.now)</span><br></pre></td></tr></table></figure><h2 id="3-4-学员感言"><a href="#3-4-学员感言" class="headerlink" title="3.4 学员感言"></a>3.4 学员感言</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StudentSay</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">img = models.CharField(max_length=<span class="number">50</span>)<span class="comment"># 头像图片 avator是头像的意思</span></span><br><span class="line">name = models.CharField(max_length=<span class="number">20</span>)</span><br><span class="line">title = models.CharField(max_length=<span class="number">255</span>)</span><br><span class="line">content = models.TextField()</span><br><span class="line">is_del = models.IntegerField(default=<span class="number">0</span>)</span><br><span class="line">join_date = models.DateTimeField(default=timezone.now)</span><br></pre></td></tr></table></figure><h2 id="3-5-技术社区内容"><a href="#3-5-技术社区内容" class="headerlink" title="3.5 技术社区内容"></a>3.5 技术社区内容</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Community</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">subject = models.CharField(max_length=<span class="number">50</span>)</span><br><span class="line"><span class="built_in">type</span> = models.CharField(max_length=<span class="number">50</span>)</span><br><span class="line">content = models.TextField()</span><br><span class="line">link = models.TextField()</span><br><span class="line">is_del = models.IntegerField(default=<span class="number">0</span>)</span><br></pre></td></tr></table></figure><h2 id="3-6-办学特色"><a href="#3-6-办学特色" class="headerlink" title="3.6 办学特色"></a>3.6 办学特色</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Feature</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">img = models.CharField(max_length=<span class="number">250</span>)</span><br><span class="line">title = models.CharField(max_length=<span class="number">250</span>)</span><br><span class="line"><span class="built_in">type</span> = models.CharField(max_length=<span class="number">250</span>)</span><br><span class="line">content = models.TextField()</span><br><span class="line">is_del = models.IntegerField(default=<span class="number">0</span>)</span><br><span class="line">join_date = models.DateTimeField(default=timezone.now)</span><br></pre></td></tr></table></figure><h2 id="3-7-课程内容"><a href="#3-7-课程内容" class="headerlink" title="3.7 课程内容"></a>3.7 课程内容</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Source</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">text = models.CharField(max_length=<span class="number">150</span>)</span><br><span class="line">link = models.CharField(max_length=<span class="number">250</span>)</span><br><span class="line">is_del = models.IntegerField(default=<span class="number">0</span>)</span><br><span class="line">join_date = models.DateTimeField(default=timezone.now)</span><br></pre></td></tr></table></figure><h2 id="3-8-个人博客"><a href="#3-8-个人博客" class="headerlink" title="3.8 个人博客"></a>3.8 个人博客</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Blog</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">name = models.CharField(max_length=<span class="number">20</span>)</span><br><span class="line">link = models.CharField(max_length=<span class="number">100</span>)</span><br><span class="line">img = models.CharField(max_length=<span class="number">255</span>)</span><br><span class="line">title = models.CharField(max_length=<span class="number">255</span>)</span><br><span class="line">description = models.TextField()</span><br><span class="line">is_del = models.IntegerField(default=<span class="number">0</span>)</span><br><span class="line">join_date = models.DateTimeField(default=timezone.now)</span><br></pre></td></tr></table></figure><h2 id="3-9-用于登录token表"><a href="#3-9-用于登录token表" class="headerlink" title="3.9 用于登录token表"></a>3.9 用于登录token表</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Token</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">token_data = models.CharField(max_length=<span class="number">250</span>)</span><br><span class="line">token_key = models.CharField(max_length=<span class="number">250</span>)</span><br><span class="line">change_time = models.DateTimeField(<span class="string">&#x27;最后修改日期&#x27;</span>,auto_now=<span class="literal">True</span>)</span><br></pre></td></tr></table></figure><h1 id="4-view视图函数"><a href="#4-view视图函数" class="headerlink" title="4.    view视图函数"></a>4.    view视图函数</h1><p>视图函数是本项目的核心,主要负责收到前端ajax的请求,进行初步的处理,然后去数据库中进行增删改查操作,并返回JSON格式的数据给请求方。具体的代码可参考附录II</p><h1 id="5-接口文档"><a href="#5-接口文档" class="headerlink" title="5.    接口文档"></a>5.    接口文档</h1><p>前后台分离后,他们两端之间的通讯是通过前台调用后台的接口实现的,所以一份清晰明了的接口文档会增加项目开发的效率,本项目的接口文档如附录中所示,其中包含了接口名称、 接口url、请求方法和请求参数。</p><h1 id="6-部署上线"><a href="#6-部署上线" class="headerlink" title="6.    部署上线"></a>6.    部署上线</h1><h2 id="6-1-域名"><a href="#6-1-域名" class="headerlink" title="6.1 域名"></a>6.1 域名</h2><p>本项目上线前需要购买一个域名,并进行域名的解析,在域名解析前需要先进行网站的备案,只有备案后才能将域名绑定在相应的服务器上面</p><h2 id="6-2-服务器"><a href="#6-2-服务器" class="headerlink" title="6.2 服务器"></a>6.2 服务器</h2><p>本项目的后台采用的是阿里云服务器,使用宝塔工具连接远程服务器,对服务器和数据库进行管理,宝塔Linux面板是提升运维效率的服务器管理软件,支持一键LAMP/LNMP/集群/监控/网站/FTP/数据库/JAVA等100多项服务器管理功能。<br>有20个人的专业团队研发及维护,经过200多个版本的迭代,功能全,少出错且足够安全,已获得全球百万用户认可安装。</p><h2 id="6-3-数据库"><a href="#6-3-数据库" class="headerlink" title="6.3 数据库"></a>6.3 数据库</h2><p>本项目的数据库使用的是mysql5.7版本,由于mysql具有开源免费等优点,加上宝塔工具的控制,进行数据库的部署也十分的方便。</p><h1 id="7-项目总结"><a href="#7-项目总结" class="headerlink" title="7.    项目总结"></a>7.    项目总结</h1><p>本项目通过采用前后端分离的方式来进行设计,能够分离减少各个项目部分之间的耦合性,一方面有利于将项目不同的部分分配给擅长不同领域的开发人员进行开发,另一方面,可以增加后期项目的可维护性。<br>整个项目用时一周,虽然其中有很多的漏洞,但是在做完整个项目后还是收获了很多的,这能够为以后的学习和工作增添一些经历和项目经验吧。<br>参考文献<br>[1]  Django项目实例精解（第2版）作者:[美]安东尼奥米勒 清华大学出版社<br>[2]  Python Web开发实战 作者:董伟明著 出版社:电子工业出版社<br>[3]  MySQL 5.7从入门到精通（视频教学版）（第2版）张工厂 清华大学出版社<br>[4]  Python Django Web典型模块开发实战 作者:寇雪松 出版社:机械工业出版社</p><h1 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h1><h2 id="附录I-接口文档"><a href="#附录I-接口文档" class="headerlink" title="附录I 接口文档"></a>附录I 接口文档</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line">后台接口名称 接口url 请求方法 请求参数</span><br><span class="line">登录用于管理员登录&#x2F;bgapi&#x2F;login&#x2F;post请求username</span><br><span class="line">　获取验证码&#x2F;bgapi&#x2F;verification&#x2F;</span><br><span class="line">博客列表&#x2F;bgapi&#x2F;blog&#x2F;list&#x2F; get请求　</span><br><span class="line">博客</span><br><span class="line">社区资源添加&#x2F;bgapi&#x2F;blog&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;blog&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;blog&#x2F;del&#x2F; get请求?id&#x3D;1</span><br><span class="line">列表&#x2F;bgapi&#x2F;community&#x2F;list&#x2F; get请求　</span><br><span class="line">社区资源</span><br><span class="line">轮播图添加&#x2F;bgapi&#x2F;community&#x2F;add&#x2F;post请求subject,</span><br><span class="line">修改&#x2F;bgapi&#x2F;community&#x2F;edit&#x2F;post请求id,subject,</span><br><span class="line">删除&#x2F;bgapi&#x2F;community&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;banner&#x2F;list&#x2F; get请求啥也不用</span><br><span class="line">轮播图</span><br><span class="line">学生视频添加&#x2F;bgapi&#x2F;banner&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;banner&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;banner&#x2F;del&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;assessvideo&#x2F;list&#x2F; get请求　</span><br><span class="line">学生视频</span><br><span class="line">办学特色添加&#x2F;bgapi&#x2F;assessvideo&#x2F;add&#x2F;post请求video,img</span><br><span class="line">修改&#x2F;bgapi&#x2F;assessvideo&#x2F;edit&#x2F;post请求video,img</span><br><span class="line">删除&#x2F;bgapi&#x2F;assessvideo&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;feature&#x2F;list&#x2F; get请求　</span><br><span class="line">办学特色</span><br><span class="line">首页信息添加&#x2F;bgapi&#x2F;feature&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;feature&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;feature&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;mainpuretext&#x2F;list&#x2F; get请求　</span><br><span class="line">首页信息</span><br><span class="line">首页学科添加&#x2F;bgapi&#x2F;mainpuretext&#x2F;add&#x2F;post请求title,content</span><br><span class="line">修改&#x2F;bgapi&#x2F;mainpuretext&#x2F;edit&#x2F;post请求id,title,content</span><br><span class="line">删除&#x2F;bgapi&#x2F;mainpuretext&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;mainsubject&#x2F;list&#x2F; get请求　</span><br><span class="line">首页学科</span><br><span class="line">阶段管理添加&#x2F;bgapi&#x2F;mainsubject&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;mainsubject&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;mainsubject&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;stage&#x2F;list&#x2F; get请求　</span><br><span class="line">阶段管理</span><br><span class="line">学员感言添加&#x2F;bgapi&#x2F;stage&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;stage&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;stage&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;studentsay&#x2F;list&#x2F; get请求　</span><br><span class="line">学员感言</span><br><span class="line">学员作品添加&#x2F;bgapi&#x2F;studentsay&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;studentsay&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;studentsay&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;studentworks&#x2F;list&#x2F; get请求　</span><br><span class="line">学员作品</span><br><span class="line">工作信息添加&#x2F;bgapi&#x2F;studentworks&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;studentworks&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;studentworks&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;jobinfo&#x2F;list&#x2F; get请求　</span><br><span class="line">工作信息</span><br><span class="line">教师信息添加&#x2F;bgapi&#x2F;jobinfo&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;jobinfo&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;jobinfo&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;teacher&#x2F;list&#x2F; get请求　</span><br><span class="line">教师信息</span><br><span class="line">课程详情添加&#x2F;bgapi&#x2F;teacher&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;teacher&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;teacher&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;coursedetail&#x2F;list&#x2F; get请求　</span><br><span class="line">课程详情</span><br><span class="line">活动管理添加&#x2F;bgapi&#x2F;coursedetail&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;coursedetail&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;coursedetail&#x2F;delete&#x2F; get请求id</span><br><span class="line">列表&#x2F;bgapi&#x2F;activity&#x2F;list&#x2F; get请求　</span><br><span class="line">活动管理添加&#x2F;bgapi&#x2F;activity&#x2F;add&#x2F;post请求name&#x3D;file</span><br><span class="line">修改&#x2F;bgapi&#x2F;activity&#x2F;edit&#x2F;post请求name&#x3D;file</span><br><span class="line">删除&#x2F;bgapi&#x2F;activity&#x2F;delete&#x2F; get请求id</span><br></pre></td></tr></table></figure><h2 id="附录II-视图函数程序代码"><a href="#附录II-视图函数程序代码" class="headerlink" title="附录II:视图函数程序代码"></a>附录II:视图函数程序代码</h2><p>课程管理视图函数</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> django.forms <span class="keyword">import</span> model_to_dict</span><br><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> render</span><br><span class="line"><span class="keyword">from</span> django.http <span class="keyword">import</span> JsonResponse,HttpResponse</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> api.models <span class="keyword">import</span> CourseDetail,Token</span><br><span class="line"><span class="keyword">from</span> django.conf <span class="keyword">import</span> settings</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> .utils <span class="keyword">import</span> add_data,edit_data,delete_data,list_data,check_token,check_md5</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">list</span>(<span class="params">request</span>):</span></span><br><span class="line">    <span class="keyword">if</span> check_token(request):</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;509&quot;</span>,</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;请先登录!&quot;</span>,</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> JsonResponse(u_dict)</span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    列表显示视图函数</span></span><br><span class="line"><span class="string">    :param request:请求参数</span></span><br><span class="line"><span class="string">    :return:返回json格式数据</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    <span class="comment"># # 验证是否登录</span></span><br><span class="line">    <span class="comment"># if check_token(request):</span></span><br><span class="line">    <span class="comment">#     # 如果成了</span></span><br><span class="line">    <span class="comment">#     pass</span></span><br><span class="line">    <span class="comment"># else:</span></span><br><span class="line">    <span class="comment">#     u_dict = &#123;</span></span><br><span class="line">    <span class="comment">#         &quot;status&quot;: &quot;509&quot;,</span></span><br><span class="line">    <span class="comment">#         &quot;info&quot;: &quot;请先登录!&quot;,</span></span><br><span class="line">    <span class="comment">#     &#125;</span></span><br><span class="line">    <span class="comment">#     return JsonResponse(u_dict)</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 验证完了</span></span><br><span class="line">    u_dict = list_data(CourseDetail)</span><br><span class="line">    response = JsonResponse(u_dict)</span><br><span class="line">    <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add</span>(<span class="params">request</span>):</span></span><br><span class="line">    <span class="comment"># 验证是否登录</span></span><br><span class="line">    <span class="keyword">if</span> check_md5(request):</span><br><span class="line">        <span class="comment"># 如果成了</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;509&quot;</span>,</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;请先登录!&quot;</span>,</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> JsonResponse(u_dict)</span><br><span class="line">    <span class="comment"># 验证完了</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    添加视图函数</span></span><br><span class="line"><span class="string">    :param request:请求参数</span></span><br><span class="line"><span class="string">    :return:返回json格式数据</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    u_dict = add_data(request,CourseDetail)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> JsonResponse(u_dict)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">edit</span>(<span class="params">request</span>):</span></span><br><span class="line">    <span class="comment"># 验证是否登录</span></span><br><span class="line">    <span class="keyword">if</span> check_md5(request):</span><br><span class="line">        <span class="comment"># 如果成了</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;509&quot;</span>,</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;请先登录!&quot;</span>,</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> JsonResponse(u_dict)</span><br><span class="line">    <span class="comment"># 验证完了</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    编辑视图函数</span></span><br><span class="line"><span class="string">    :param request:请求参数</span></span><br><span class="line"><span class="string">    :return:返回json格式数据</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    u_dict = edit_data(request,CourseDetail)</span><br><span class="line">    <span class="keyword">return</span> JsonResponse(u_dict)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">delete</span>(<span class="params">request</span>):</span></span><br><span class="line">    <span class="comment"># 验证是否登录</span></span><br><span class="line">    <span class="keyword">if</span> check_token(request):</span><br><span class="line">        <span class="comment"># 如果成了</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;509&quot;</span>,</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;请先登录!&quot;</span>,</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> JsonResponse(u_dict)</span><br><span class="line">    <span class="comment"># 验证完了</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    删除视图函数</span></span><br><span class="line"><span class="string">    :param request:请求参数</span></span><br><span class="line"><span class="string">    :return:返回json格式数据</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    u_dict = delete_data(request,CourseDetail)</span><br><span class="line">    <span class="keyword">return</span> JsonResponse(u_dict)</span><br><span class="line">封装工具类</span><br><span class="line">保存文件</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">save_file</span>(<span class="params">file</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    用于保存文件,返回保存文件的路径</span></span><br><span class="line"><span class="string">    :param file:</span></span><br><span class="line"><span class="string">    :return:</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    <span class="keyword">if</span> file:</span><br><span class="line">        <span class="comment"># 上传了头像</span></span><br><span class="line">        <span class="keyword">import</span> hashlib</span><br><span class="line">        <span class="comment"># 待加密信息(随机数)</span></span><br><span class="line">        ran_str = <span class="built_in">str</span>(random.randint(<span class="number">0</span>, <span class="number">9999999</span>))</span><br><span class="line">        <span class="comment"># 创建md5对象</span></span><br><span class="line">        hl = hashlib.md5()</span><br><span class="line">        to_md5_str = <span class="built_in">str</span>(time()) + ran_str</span><br><span class="line">        <span class="comment"># Tips</span></span><br><span class="line">        <span class="comment"># 此处必须声明encode</span></span><br><span class="line">        <span class="comment"># 若写法为hl.update(str)  报错为： Unicode-objects must be encoded before hashing</span></span><br><span class="line">        hl.update(to_md5_str.encode(encoding=<span class="string">&#x27;utf-8&#x27;</span>))</span><br><span class="line">        <span class="comment"># 加密完的md5字符串</span></span><br><span class="line">        md5_str = hl.hexdigest()</span><br><span class="line">        <span class="comment"># 文件扩展名</span></span><br><span class="line">        file_extend_name = file.name.split(<span class="string">&#x27;.&#x27;</span>).pop()</span><br><span class="line">        <span class="comment"># 拼接文件名</span></span><br><span class="line">        filename = md5_str + <span class="string">&#x27;.&#x27;</span> + file_extend_name</span><br><span class="line"></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">f&#x27;./media/&#x27;</span> + filename, <span class="string">&#x27;wb+&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            f.write(file.read())</span><br><span class="line">        <span class="comment"># with open(f&#x27;./media/uploads/&#x27; + filename, &#x27;wb+&#x27;) as fp:</span></span><br><span class="line">        <span class="comment">#     fp.write(file.read())</span></span><br><span class="line">        <span class="keyword">return</span> filename</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line">删除文件</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">del_file</span>(<span class="params">path</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    用于删除文件,返回删没删成功</span></span><br><span class="line"><span class="string">    :param path:</span></span><br><span class="line"><span class="string">    :return:</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    <span class="keyword">import</span> os</span><br><span class="line">    my_file = settings.BASE_DIR + settings.MEDIA_URL + path</span><br><span class="line">    print(my_file)</span><br><span class="line">    <span class="keyword">if</span> os.path.exists(my_file):</span><br><span class="line">        <span class="comment"># 删除文件,可使用以下两种方法。</span></span><br><span class="line">        os.remove(my_file)</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line">成功返回数据</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">success_response</span>(<span class="params">u_dict</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    正确返回数据 过滤器</span></span><br><span class="line"><span class="string">    :param u_dict: 返回的数据主体内容</span></span><br><span class="line"><span class="string">    :return: 嵌套后的数据</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    u_dict = &#123;</span><br><span class="line">        <span class="string">&quot;status&quot;</span>: <span class="string">&quot;200&quot;</span>,</span><br><span class="line">        <span class="string">&quot;info&quot;</span>: <span class="string">&quot;返回信息成功!&quot;</span>,</span><br><span class="line">        <span class="string">&quot;data&quot;</span>: u_dict</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> u_dict</span><br><span class="line"></span><br><span class="line">返回错误信息</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">error_response</span>(<span class="params">u_dict, err_info</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    返回错误json</span></span><br><span class="line"><span class="string">    :param u_dict: json返回的主要内容</span></span><br><span class="line"><span class="string">    :param err_info: 错误提示信息</span></span><br><span class="line"><span class="string">    :return:</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    u_dict = &#123;</span><br><span class="line">        <span class="string">&quot;status&quot;</span>: <span class="string">&quot;500&quot;</span>,</span><br><span class="line">        <span class="string">&quot;info&quot;</span>: err_info,</span><br><span class="line">        <span class="string">&quot;data&quot;</span>: u_dict</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> u_dict</span><br><span class="line"></span><br><span class="line">查询数据</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">list_data</span>(<span class="params">a_model_object</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    用于列表返回所有数据库数据</span></span><br><span class="line"><span class="string">    :param a_model_object: 一个模型对象</span></span><br><span class="line"><span class="string">    :return: 返回json数据格式的字典dict类型数据</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    print(<span class="string">&quot;--------------------------开始列表视图函数---------------------------&quot;</span>)</span><br><span class="line">    u_dict = &#123;&#125;</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        u_dict = all_data(a_model_object)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 嵌套一层</span></span><br><span class="line">        u_dict = success_response(u_dict)</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        u_dict = error_response(u_dict, <span class="string">&quot;服务器错误,查询异常!&quot;</span>)</span><br><span class="line">    <span class="keyword">return</span> u_dict</span><br><span class="line">添加数据</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_data</span>(<span class="params">request, a_model_object</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    封装的添加方法</span></span><br><span class="line"><span class="string">    :param request: http的请求request参数</span></span><br><span class="line"><span class="string">    :param a_model_object: 一个模型对象</span></span><br><span class="line"><span class="string">    :return: 返回json之前的字典类型的数据</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    print(<span class="string">&quot;--------------------------开始添加视图函数---------------------------&quot;</span>)</span><br><span class="line">    <span class="comment"># 定义返回数据</span></span><br><span class="line">    u_dict = &#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment"># 判断请求方式</span></span><br><span class="line">    <span class="keyword">if</span> (request.method == <span class="string">&#x27;POST&#x27;</span>):</span><br><span class="line">        <span class="comment"># try:</span></span><br><span class="line">        <span class="comment"># 开始处理图片</span></span><br><span class="line">        <span class="comment"># 1.获取表单内容</span></span><br><span class="line">        data = request.POST.<span class="built_in">dict</span>()</span><br><span class="line">        print(data)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 要是有link,那就判断一下是不是真的link</span></span><br><span class="line">        <span class="keyword">if</span> <span class="string">&quot;link&quot;</span> <span class="keyword">in</span> data.keys():</span><br><span class="line">            curr_link = data[<span class="string">&quot;link&quot;</span>]</span><br><span class="line">            <span class="keyword">if</span> check_link(curr_link):</span><br><span class="line">                <span class="comment"># 要是链接,啥也不干</span></span><br><span class="line">                <span class="keyword">pass</span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="comment"># 要是不行,那直接就给踢回去</span></span><br><span class="line">                u_dict = &#123;</span><br><span class="line">                    <span class="string">&quot;info&quot;</span>: <span class="string">&quot;链接类型不正确,请检查格式!&quot;</span>,</span><br><span class="line">                    <span class="string">&quot;status&quot;</span>: <span class="string">&quot;506&quot;</span></span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">return</span> u_dict</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 先删除token</span></span><br><span class="line">        data.pop(<span class="string">&quot;token&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 2. 获取表单中的文件</span></span><br><span class="line">        file = request.FILES.get(<span class="string">&#x27;file&#x27;</span>, <span class="literal">None</span>)</span><br><span class="line">        print(<span class="string">&quot;file&quot;</span>, file)</span><br><span class="line">        <span class="comment"># 3. 执行保存文件,并返回文件路径</span></span><br><span class="line">        <span class="comment"># save_file ---&gt; 自定义函数</span></span><br><span class="line">        path = save_file(file)</span><br><span class="line">        <span class="comment"># TODO 这里判断文件类型</span></span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            kind = filetype.guess(settings.BASE_DIR+settings.MEDIA_URL+path)</span><br><span class="line">            print(<span class="string">&quot;猜出来的类型是:&quot;</span>,kind)</span><br><span class="line">            print(<span class="string">&quot;猜出来的类型extension是:&quot;</span>,kind.extension)</span><br><span class="line">            print(<span class="string">&quot;猜出来的类型mime是:&quot;</span>,kind.mime)</span><br><span class="line">            <span class="comment"># <span class="doctag">TODO:</span> write code.....</span></span><br><span class="line">            <span class="comment"># # 判断真的文件类型</span></span><br><span class="line">            <span class="keyword">if</span> kind.extension == <span class="string">&quot;png&quot;</span> <span class="keyword">or</span> kind.extension == <span class="string">&quot;jpg&quot;</span>:</span><br><span class="line">                <span class="comment"># 要是符合类型的,啥也不干</span></span><br><span class="line">                <span class="keyword">pass</span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="comment"># 要不是这俩类型</span></span><br><span class="line">                <span class="comment"># 直接我就返回,错误信息</span></span><br><span class="line">                u_dict = &#123;</span><br><span class="line">                    <span class="string">&quot;info&quot;</span>: <span class="string">&quot;图片类型不正确,请上传png或者jpg格式!&quot;</span>,</span><br><span class="line">                    <span class="string">&quot;status&quot;</span>: <span class="string">&quot;505&quot;</span></span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">return</span> u_dict</span><br><span class="line">        <span class="keyword">except</span>:</span><br><span class="line">            u_dict = &#123;</span><br><span class="line">                <span class="string">&quot;info&quot;</span>: <span class="string">&quot;图片类型不正确,请上传png或者jpg格式!&quot;</span>,</span><br><span class="line">                <span class="string">&quot;status&quot;</span>: <span class="string">&quot;505&quot;</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> u_dict</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> path:</span><br><span class="line">            data.pop(<span class="string">&quot;file&quot;</span>)</span><br><span class="line">        <span class="comment"># 构建img字段数据</span></span><br><span class="line">        data[<span class="string">&quot;img&quot;</span>] = path</span><br><span class="line">        <span class="comment"># data.pop(&quot;file&quot;)</span></span><br><span class="line">        <span class="comment"># 保存数据</span></span><br><span class="line">        a_model_object(**data).save()</span><br><span class="line">        <span class="comment"># 返回数据内容</span></span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;ok&quot;</span>,</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;200&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment"># except:</span></span><br><span class="line">        <span class="comment">#     u_dict = &#123;</span></span><br><span class="line">        <span class="comment">#         &quot;info&quot;: &quot;error&quot;,</span></span><br><span class="line">        <span class="comment">#         &quot;status&quot;: &quot;500&quot;</span></span><br><span class="line">        <span class="comment">#     &#125;</span></span><br><span class="line">    <span class="keyword">if</span> (request.method == <span class="string">&#x27;GET&#x27;</span>):</span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;缺心眼啊,用浏览器访问!&quot;</span>,</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;666&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    <span class="keyword">return</span> u_dict</span><br><span class="line">修改数据</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">edit_data</span>(<span class="params">request, a_model_object</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    用于编辑的封装函数</span></span><br><span class="line"><span class="string">    :param request: 一个请求的参数</span></span><br><span class="line"><span class="string">    :param a_model_object: 一个模型类对象</span></span><br><span class="line"><span class="string">    :return: 返回提示信息的json格式字典dict</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    print(<span class="string">&quot;--------------------------开始编辑视图函数---------------------------&quot;</span>)</span><br><span class="line">    u_dict = &#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    print(<span class="string">&quot;request.POST:&quot;</span>, request.POST)</span><br><span class="line">    print(<span class="string">&quot;request.FILES:&quot;</span>, request.FILES)</span><br><span class="line">    <span class="keyword">if</span> (request.method == <span class="string">&#x27;POST&#x27;</span>):</span><br><span class="line">        <span class="comment"># 获取修改的id</span></span><br><span class="line">        data = request.POST.<span class="built_in">dict</span>()</span><br><span class="line">        print(data)</span><br><span class="line">        <span class="comment"># 先删除token</span></span><br><span class="line">        data.pop(<span class="string">&quot;token&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 要是有link,那就判断一下是不是真的link</span></span><br><span class="line">        <span class="keyword">if</span> <span class="string">&quot;link&quot;</span> <span class="keyword">in</span> data.keys():</span><br><span class="line">            curr_link = data[<span class="string">&quot;link&quot;</span>]</span><br><span class="line">            <span class="keyword">if</span> check_link(curr_link):</span><br><span class="line">                <span class="comment"># 要是链接,啥也不干</span></span><br><span class="line">                <span class="keyword">pass</span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="comment"># 要是不行,那直接就给踢回去</span></span><br><span class="line">                u_dict = &#123;</span><br><span class="line">                    <span class="string">&quot;info&quot;</span>: <span class="string">&quot;链接类型不正确,请检查格式!&quot;</span>,</span><br><span class="line">                    <span class="string">&quot;status&quot;</span>: <span class="string">&quot;506&quot;</span></span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">return</span> u_dict</span><br><span class="line"></span><br><span class="line">        <span class="comment"># print(data.__dict__)</span></span><br><span class="line">        <span class="built_in">id</span> = data[<span class="string">&quot;id&quot;</span>]</span><br><span class="line">        <span class="comment"># 获取原来的对象</span></span><br><span class="line">        obj = a_model_object.objects.get(<span class="built_in">id</span>=<span class="built_in">id</span>)</span><br><span class="line">        <span class="built_in">dict</span> = model_to_dict(obj)</span><br><span class="line">        old_path = <span class="built_in">dict</span>[<span class="string">&#x27;img&#x27;</span>]</span><br><span class="line">        <span class="comment"># 2. 获取表单中的文件</span></span><br><span class="line">        new_file = request.FILES.get(<span class="string">&#x27;file&#x27;</span>, <span class="literal">None</span>)</span><br><span class="line">        <span class="comment"># 判断有没有新文件</span></span><br><span class="line">        print(<span class="string">&quot;new_file:&quot;</span>, new_file)</span><br><span class="line">        <span class="comment"># 要是有新文件的话</span></span><br><span class="line">        <span class="keyword">if</span> new_file:</span><br><span class="line">            <span class="comment"># print(new_file)</span></span><br><span class="line">            <span class="comment"># print(type(new_file))</span></span><br><span class="line">            <span class="comment"># print(&quot;走的有文件&quot;)</span></span><br><span class="line">            <span class="comment"># 删除旧文件</span></span><br><span class="line">            del_file(old_path)</span><br><span class="line">            <span class="comment"># 保存新文件</span></span><br><span class="line">            path = save_file(new_file)</span><br><span class="line">            print(<span class="string">&quot;new_path:&quot;</span>, path)</span><br><span class="line">            <span class="comment"># 构建img字段数据</span></span><br><span class="line">            data[<span class="string">&quot;img&quot;</span>] = path</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="comment"># print(&quot;走的没文件&quot;)</span></span><br><span class="line">            <span class="comment"># print(new_file)</span></span><br><span class="line">            <span class="comment"># print(type(new_file))</span></span><br><span class="line">            <span class="comment"># 没有新文件</span></span><br><span class="line">            data[<span class="string">&quot;img&quot;</span>] = old_path</span><br><span class="line">            data.pop(<span class="string">&quot;file&quot;</span>)</span><br><span class="line"></span><br><span class="line">        obj = a_model_object.objects.<span class="built_in">filter</span>(<span class="built_in">id</span>=<span class="built_in">id</span>)</span><br><span class="line">        obj.update(**data)</span><br><span class="line">        <span class="comment"># else:</span></span><br><span class="line">        <span class="comment">#     u_dict = &#123;</span></span><br><span class="line">        <span class="comment">#         &quot;info&quot;: &quot;删除文件失败!&quot;,</span></span><br><span class="line">        <span class="comment">#         &quot;status&quot;: &quot;501&quot;</span></span><br><span class="line">        <span class="comment">#     &#125;</span></span><br><span class="line">        <span class="comment">#     return JsonResponse(u_dict)</span></span><br><span class="line">        <span class="comment"># 成功状态码</span></span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;ok&quot;</span>,</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;200&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    <span class="keyword">if</span> (request.method == <span class="string">&#x27;GET&#x27;</span>):</span><br><span class="line">        <span class="comment"># 请求方式不对状态码</span></span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;no&quot;</span>,</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;666&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    <span class="keyword">return</span> u_dict</span><br><span class="line">删除数据</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">delete_data</span>(<span class="params">request, a_model_object</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    用于删除封装的方法</span></span><br><span class="line"><span class="string">    :param request: 一个请求参数</span></span><br><span class="line"><span class="string">    :param a_model_object: 一个模型对象</span></span><br><span class="line"><span class="string">    :return: 返回json类型的字典数据</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    u_dict = &#123;</span><br><span class="line">        <span class="string">&quot;info&quot;</span>: <span class="string">&quot;default&quot;</span>,</span><br><span class="line">        <span class="string">&quot;status&quot;</span>: <span class="string">&quot;888&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">    print(<span class="string">&quot;--------------------------开始删除视图函数---------------------------&quot;</span>)</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="comment"># 尝试删除</span></span><br><span class="line">        <span class="built_in">id</span> = request.GET.get(<span class="string">&quot;id&quot;</span>)</span><br><span class="line">        obj = a_model_object.objects.get(<span class="built_in">id</span>=<span class="built_in">id</span>)</span><br><span class="line">        <span class="comment"># 删除源文件</span></span><br><span class="line">        <span class="comment"># 获取文件路径</span></span><br><span class="line">        <span class="built_in">dict</span> = model_to_dict(obj)</span><br><span class="line">        <span class="comment"># 删除库</span></span><br><span class="line">        obj.delete()</span><br><span class="line">        <span class="comment"># 原始路径</span></span><br><span class="line">        old_path = <span class="built_in">dict</span>[<span class="string">&#x27;img&#x27;</span>]</span><br><span class="line">        print(<span class="string">&quot;old_path:&quot;</span>, old_path)</span><br><span class="line">        <span class="comment"># 执行删除</span></span><br><span class="line">        del_file(old_path)</span><br><span class="line"></span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;ok&quot;</span>,</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;200&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        u_dict = &#123;</span><br><span class="line">            <span class="string">&quot;info&quot;</span>: <span class="string">&quot;error&quot;</span>,</span><br><span class="line">            <span class="string">&quot;status&quot;</span>: <span class="string">&quot;500&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    <span class="keyword">return</span> u_dict</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django项目-慕学在线平台</title>
      <link href="python/Django/django-project/"/>
      <url>python/Django/django-project/</url>
      
        <content type="html"><![CDATA[<p>开发环境：</p><p>　　　　python:  3.6.4</p><p>　　　　Django: 2.0.2</p><p>后台管理：xadmin</p><h3 id="1-1-项目介绍"><a href="#1-1-项目介绍" class="headerlink" title="1.1.项目介绍"></a>1.1.项目介绍</h3><p>系统概括：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">系统具有完整的用户登录注册以及找回密码功能，拥有完整个人中心。</span><br><span class="line">个人中心: 修改头像，修改密码，修改邮箱，可以看到我的课程以及我的收藏。可以删除收藏，我的消息。</span><br><span class="line">导航栏: 公开课，授课讲师，授课机构，全局搜索。</span><br><span class="line">点击公开课–&gt; 课程列表，排序-搜索。热门课程推荐，课程的分页。</span><br><span class="line">点击课程–&gt; 课程详情页中对课程进行收藏，取消收藏。富文本展示课程内容。</span><br><span class="line">点击开始学习–&gt; 课程的章节信息，课程的评论信息。课程资源的下载链接。</span><br><span class="line">点击授课讲师–&gt;授课讲师列表页，对讲师进行人气排序以及分页，右边有讲师排行榜。</span><br><span class="line">点击讲师的详情页面–&gt; 对讲师进行收藏和分享，以及讲师的全部课程。</span><br><span class="line">导航栏: 授课机构有分页，排序筛选功能。</span><br><span class="line">机构列表页右侧有快速提交我要学习的表单。</span><br><span class="line">点击机构–&gt; 左侧：机构首页,机构课程，机构介绍，机构讲师。</span><br><span class="line">后台管理系统可以切换主题。左侧每一个功能都有列表显示, 增删改查，筛选功能。</span><br><span class="line">课程列表页可以对不同字段进行排序。选择多条记录进行删除操作。</span><br><span class="line">课程列表页：过滤器-&gt;选择字段范围等,搜索,导出csv，xml，json。</span><br><span class="line">课程新增页面上传图片，富文本的编辑。时间选择，添加章节，添加课程资源。</span><br><span class="line">日志记录：记录后台人员的操作</span><br></pre></td></tr></table></figure><h3 id="1-2-创建工程"><a href="#1-2-创建工程" class="headerlink" title="1.2.创建工程"></a>1.2.创建工程</h3><h4 id="创建工程"><a href="#创建工程" class="headerlink" title="创建工程"></a>创建工程</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">django-admin startproject MxOnline</span><br></pre></td></tr></table></figure><h4 id="创建四个app"><a href="#创建四个app" class="headerlink" title="创建四个app"></a>创建四个app</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">python manage.py startapp users</span><br><span class="line"></span><br><span class="line">python manage.py startapp course</span><br><span class="line"></span><br><span class="line">python manage.py startapp organization</span><br><span class="line"></span><br><span class="line">python manage.py startapp operation</span><br></pre></td></tr></table></figure><p>然后分别设计每个app的models</p><h3 id="2-1-users-用户"><a href="#2-1-users-用户" class="headerlink" title="2.1.users 用户"></a>2.1.users 用户</h3><h4 id="自定义userProfile"><a href="#自定义userProfile" class="headerlink" title="自定义userProfile"></a>自定义userProfile</h4><p> 系统自动生成的user表如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">id: 主键, password 密码, last_login Django自动记录用户最后登录时间,。</span><br><span class="line">is_superuser 表明用户是否是超级用户(后台管理会用到)。</span><br><span class="line">username 用户名字段不要随便改动, email 邮箱,</span><br><span class="line">is_staff 表示是否是员工(后台管理会用到)。</span><br><span class="line">is_active 用户是否是激活状态, date_joined 注册时间。</span><br></pre></td></tr></table></figure><p>users/models.py添加代码:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># users/models.py</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"><span class="keyword">from</span> django.contrib.auth.models <span class="keyword">import</span> AbstractUser</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserProfile</span>(<span class="params">AbstractUser</span>):</span></span><br><span class="line"></span><br><span class="line">    gender_choices = (</span><br><span class="line">        (<span class="string">&#x27;male&#x27;</span>,<span class="string">&#x27;男&#x27;</span>),</span><br><span class="line">        (<span class="string">&#x27;female&#x27;</span>,<span class="string">&#x27;女&#x27;</span>)</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    nick_name = models.CharField(<span class="string">&#x27;昵称&#x27;</span>,max_length=<span class="number">50</span>,default=<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    birthday = models.DateField(<span class="string">&#x27;生日&#x27;</span>,null=<span class="literal">True</span>,blank=<span class="literal">True</span>)</span><br><span class="line">    gender = models.CharField(<span class="string">&#x27;性别&#x27;</span>,max_length=<span class="number">10</span>,choices=gender_choices,default=<span class="string">&#x27;female&#x27;</span>)</span><br><span class="line">    adress = models.CharField(<span class="string">&#x27;地址&#x27;</span>,max_length=<span class="number">100</span>,default=<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    mobile = models.CharField(<span class="string">&#x27;手机号&#x27;</span>,max_length=<span class="number">11</span>,null=<span class="literal">True</span>,blank=<span class="literal">True</span>)</span><br><span class="line">    image = models.ImageField(upload_to=<span class="string">&#x27;image/%Y%m&#x27;</span>,default=<span class="string">&#x27;image/default.png&#x27;</span>,max_length=<span class="number">100</span>)</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        verbose_name = <span class="string">&#x27;用户信息&#x27;</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">return</span> self.username</span><br></pre></td></tr></table></figure><p>然后做下面的一些设置</p><p>因为Image字段需要用到pillow所以需要安装该库</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install pillow</span><br></pre></td></tr></table></figure><h3 id="注册app"><a href="#注册app" class="headerlink" title="注册app"></a>注册app</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">INSTALLED_APPS &#x3D; [</span><br><span class="line">    &#39;django.contrib.admin&#39;,</span><br><span class="line">    &#39;django.contrib.auth&#39;,</span><br><span class="line">    &#39;django.contrib.contenttypes&#39;,</span><br><span class="line">    &#39;django.contrib.sessions&#39;,</span><br><span class="line">    &#39;django.contrib.messages&#39;,</span><br><span class="line">    &#39;django.contrib.staticfiles&#39;,</span><br><span class="line">    &#39;users&#39;</span><br><span class="line">]</span><br></pre></td></tr></table></figure><h3 id="重载AUTH-USER-MODEL"><a href="#重载AUTH-USER-MODEL" class="headerlink" title="重载AUTH_USER_MODEL"></a>重载AUTH_USER_MODEL</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AUTH_USER_MODEL &#x3D; &#39;users.UserProfile&#39;</span><br></pre></td></tr></table></figure><h3 id="设计数据库为Mysql"><a href="#设计数据库为Mysql" class="headerlink" title="设计数据库为Mysql"></a>设计数据库为Mysql</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># DATABASES = &#123;</span></span><br><span class="line"><span class="comment">#     &#x27;default&#x27;: &#123;</span></span><br><span class="line"><span class="comment">#         &#x27;ENGINE&#x27;: &#x27;django.db.backends.sqlite3&#x27;,</span></span><br><span class="line"><span class="comment">#         &#x27;NAME&#x27;: os.path.join(BASE_DIR, &#x27;db.sqlite3&#x27;),</span></span><br><span class="line"><span class="comment">#     &#125;</span></span><br><span class="line"><span class="comment"># &#125;</span></span><br><span class="line"></span><br><span class="line">DATABASES = &#123;</span><br><span class="line">    <span class="string">&#x27;default&#x27;</span>: &#123;</span><br><span class="line">        <span class="string">&#x27;ENGINE&#x27;</span>: <span class="string">&#x27;django.db.backends.mysql&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;NAME&#x27;</span>: <span class="string">&#x27;mxonline&#x27;</span>,        <span class="comment">#数据库名字</span></span><br><span class="line">        <span class="string">&#x27;USER&#x27;</span>: <span class="string">&#x27;root&#x27;</span>,          <span class="comment">#账号</span></span><br><span class="line">        <span class="string">&#x27;PASSWORD&#x27;</span>: <span class="string">&#x27;123456&#x27;</span>,      <span class="comment">#密码</span></span><br><span class="line">        <span class="string">&#x27;HOST&#x27;</span>: <span class="string">&#x27;127.0.0.1&#x27;</span>,    <span class="comment">#IP</span></span><br><span class="line">        <span class="string">&#x27;PORT&#x27;</span>: <span class="string">&#x27;3306&#x27;</span>,                   <span class="comment">#端口</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="init-py里面导入pymysql模块"><a href="#init-py里面导入pymysql模块" class="headerlink" title="init.py里面导入pymysql模块"></a>init.py里面导入pymysql模块</h3><h1 id="user-init-py"><a href="#user-init-py" class="headerlink" title="user/init.py"></a>user/<strong>init</strong>.py</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">import pymysql</span><br><span class="line">pymysql.install_as_MySQLdb()</span><br></pre></td></tr></table></figure><h3 id="迁移数据库"><a href="#迁移数据库" class="headerlink" title="迁移数据库"></a>迁移数据库</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">python manage.py makemigrations</span><br><span class="line"></span><br><span class="line">python manage.py migrate</span><br></pre></td></tr></table></figure><h3 id="2-5-把四个app放到一个文件夹"><a href="#2-5-把四个app放到一个文件夹" class="headerlink" title="2.5.把四个app放到一个文件夹"></a>2.5.把四个app放到一个文件夹</h3><p>创建package: apps</p><p>把之前的四个app全部剪切到apps包里面<br>** 不要选“Search for references”**<br>去掉searchfor的勾选。拖进去之后会报错，说找不到那些import的模块了。</p><p>解决方案：右键Mark为sourceRoot。根目录下找不到的，会去apps下搜索。</p><p> 但是这时候cmd下还是会报错。需要在settings设置</p><p>插入第0是希望它先搜索我们app下东西：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="comment"># Build paths inside the project like this: os.path.join(BASE_DIR, ...)</span></span><br><span class="line">BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))</span><br><span class="line">sys.path.insert(<span class="number">0</span>,os.path.join(BASE_DIR,<span class="string">&#x27;apps&#x27;</span>))</span><br></pre></td></tr></table></figure><p>再运行就可以成功启动了</p><h2 id="三、xadmin后台管理"><a href="#三、xadmin后台管理" class="headerlink" title="三、xadmin后台管理"></a>三、xadmin后台管理</h2><h3 id="3-1-xadmin的安装"><a href="#3-1-xadmin的安装" class="headerlink" title="3.1.xadmin的安装"></a>3.1.xadmin的安装</h3><h4 id="django2-0的安装（源码安装方式）："><a href="#django2-0的安装（源码安装方式）：" class="headerlink" title="django2.0的安装（源码安装方式）："></a>django2.0的安装（源码安装方式）：</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:&#x2F;&#x2F;github.com&#x2F;sshwsfc&#x2F;xadmin&#x2F;tree&#x2F;django2</span><br></pre></td></tr></table></figure><p>把zip文件放到pip目录下，运行下面命令安装：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install xadmin-django2</span><br></pre></td></tr></table></figure><p>如果上面安装提示Runtime错误：</p><p>更换安装源（使用豆瓣源）</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -i https:&#x2F;&#x2F;pypi.douban.com&#x2F;simple xadmin-django2</span><br></pre></td></tr></table></figure><p>安装成功后，同时也安装了很多依赖的包。</p><h3 id="3-2-xadmin的设置"><a href="#3-2-xadmin的设置" class="headerlink" title="3.2.xadmin的设置"></a>3.2.xadmin的设置</h3><p> （1）新建Python Package “extra_apps”,把源码xadmin文件夹放到extra_apps文件夹下面，此时目录结构如下：<br>（2）把extra_apps右键mark为Source Root并在settings中加入</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sys.path.insert(0,os.path.join(BASE_DIR, &#39;extra_apps&#39;))</span><br></pre></td></tr></table></figure><p>（3）因为我们用源码的xadmin,所以要卸载之前安装的<br>卸载</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">(venv) D:\PycharmProjects\edu_platform_django&gt;pip uninstall xadmin</span><br><span class="line">Uninstalling xadmin-2.0.1:</span><br><span class="line">  Would remove:</span><br><span class="line">    d:\pycharmprojects\edu_platform_django\venv\lib\site-packages\xadmin-2.0.1-py3.7.egg-info</span><br><span class="line">    d:\pycharmprojects\edu_platform_django\venv\lib\site-packages\xadmin\*</span><br><span class="line">Proceed (y&#x2F;n)? y</span><br><span class="line">  Successfully uninstalled xadmin-2.0.1</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>(4)配置路由<br>把admin改成xadmin</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># urls.py</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> django.urls <span class="keyword">import</span> path</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> xadmin</span><br><span class="line"></span><br><span class="line">urlpatterns = [</span><br><span class="line">    path(<span class="string">&#x27;xadmin/&#x27;</span>, xadmin.site.urls),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>(5)注册app</p><p>把下面两个app注册到settings.py的INSTALLED_APPS中</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;xadmin&#x27;</span>,</span><br><span class="line"><span class="string">&#x27;crispy_forms&#x27;</span></span><br></pre></td></tr></table></figure><p>(6)重新生成数据库</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">python manage.py makemigrations</span><br><span class="line"></span><br><span class="line">python manage.py migrate</span><br></pre></td></tr></table></figure><p>(7)设置成中文</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">LANGUAGE_CODE &#x3D; &#39;zh-hans&#39;</span><br><span class="line"></span><br><span class="line">TIME_ZONE &#x3D; &#39;Asia&#x2F;Shanghai&#39;</span><br><span class="line"></span><br><span class="line">USE_I18N &#x3D; True</span><br><span class="line"></span><br><span class="line">USE_L10N &#x3D; True</span><br><span class="line"></span><br><span class="line">USE_TZ &#x3D; False</span><br></pre></td></tr></table></figure><p>(8)创建一个管理员用户</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python manage.py createsuperuser</span><br></pre></td></tr></table></figure><p>现在就可以运行了 </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python manage.py runserver </span><br></pre></td></tr></table></figure><p>访问后台：<a href="http://127.0.0.1:8000/xadmin">http://127.0.0.1:8000/xadmin</a></p><p> 可以看到成功进入管理界面</p><h3 id="3-3-users-app的models注册"><a href="#3-3-users-app的models注册" class="headerlink" title="3.3.users app的models注册"></a>3.3.users app的models注册</h3><p>（1）在users下面创建adminx.py,代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># users/adminx.py</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> xadmin</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> .models <span class="keyword">import</span> EmailVerifyRecord</span><br><span class="line"></span><br><span class="line"><span class="comment">#xadmin中这里是继承object，不再是继承admin</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">EmailVerifyRecordAdmin</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">xadmin.site.register(EmailVerifyRecord,EmailVerifyRecordAdmin)</span><br></pre></td></tr></table></figure><p>(2)完善功能，增加显示字段，搜索和过滤</p><p>修改users/adminx.py,代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># users/adminx.py</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> xadmin</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> .models <span class="keyword">import</span> EmailVerifyRecord</span><br><span class="line"></span><br><span class="line"><span class="comment">#xadmin中这里是继承object，不再是继承admin</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">EmailVerifyRecordAdmin</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    <span class="comment"># 显示的列</span></span><br><span class="line">    list_display = [<span class="string">&#x27;code&#x27;</span>, <span class="string">&#x27;email&#x27;</span>, <span class="string">&#x27;send_type&#x27;</span>, <span class="string">&#x27;send_time&#x27;</span>]</span><br><span class="line">    <span class="comment"># 搜索的字段，不要添加时间搜索</span></span><br><span class="line">    search_fields = [<span class="string">&#x27;code&#x27;</span>, <span class="string">&#x27;email&#x27;</span>, <span class="string">&#x27;send_type&#x27;</span>]</span><br><span class="line">    <span class="comment"># 过滤</span></span><br><span class="line">    list_filter = [<span class="string">&#x27;code&#x27;</span>, <span class="string">&#x27;email&#x27;</span>, <span class="string">&#x27;send_type&#x27;</span>, <span class="string">&#x27;send_time&#x27;</span>]</span><br><span class="line"></span><br><span class="line">xadmin.site.register(EmailVerifyRecord,EmailVerifyRecordAdmin)</span><br></pre></td></tr></table></figure><h3 id="3-5-xadmin的全局配置"><a href="#3-5-xadmin的全局配置" class="headerlink" title="3.5.xadmin的全局配置"></a>3.5.xadmin的全局配置</h3><p>将全局配置修改:</p><p>如左上角：django Xadmin。下面的我的公司<br>主题修改，app名称汉化，菜单收叠。<br> 使用Xadmin的主题功能。</p><p>把全站的配置放在users\adminx.py中:</p><p>1）添加主题功能</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django models中关于blank与null的补充说明</title>
      <link href="python/Django/django-/"/>
      <url>python/Django/django-/</url>
      
        <content type="html"><![CDATA[<h2 id="建立一个简易Model"><a href="#建立一个简易Model" class="headerlink" title="建立一个简易Model"></a>建立一个简易Model</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">    GENDER_CHOICES=(</span><br><span class="line">        (<span class="number">1</span>,<span class="string">&#x27;Male&#x27;</span>),</span><br><span class="line">        (<span class="number">2</span>,<span class="string">&#x27;Female&#x27;</span>),</span><br><span class="line">        )</span><br><span class="line">    name=models.CharField(max_length=<span class="number">30</span>,unique=<span class="literal">True</span>,verbose_name=<span class="string">&#x27;姓 名&#x27;</span>)   </span><br><span class="line">    birthday=models.DateField(blank=<span class="literal">True</span>,null=<span class="literal">True</span>)</span><br><span class="line">    gender=models.IntegerField(choices=GENDER_CHOICES)</span><br><span class="line">    account=models.IntegerField(default=<span class="number">0</span>)　　</span><br></pre></td></tr></table></figure><h2 id="blank"><a href="#blank" class="headerlink" title="blank"></a>blank</h2><p>设置为True时，字段可以为空。设置为False时，字段是必须填写的。字符型字段CharField和TextField是用空字符串来存储空值的。<br><strong>如果为True，字段允许为空，默认不允许。</strong></p><h2 id="null"><a href="#null" class="headerlink" title="null"></a>null</h2><p>设置为True时，django用Null来存储空值。日期型、时间型和数字型字段不接受空字符串。所以设置IntegerField，DateTimeField型字段可以为空时，需要将blank，null均设为True。<br><strong>如果为True，空值将会被存储为NULL，默认为False。</strong><br>如果想设置BooleanField为空时可以选用NullBooleanField型字段。</p><h2 id="一句话概括"><a href="#一句话概括" class="headerlink" title="一句话概括"></a>一句话概括</h2><ul><li>null 是针对数据库而言，如果 null=True, 表示数据库的该字段可以为空。</li><li>blank 是针对表单的，如果 blank=True，表示你的表单填写该字段的时候可以不填，比如 admin 界面下增加 model 一条记录的时候。直观的看到就是该字段不是粗体</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>常用链接汇总</title>
      <link href="comic/link/"/>
      <url>comic/link/</url>
      
        <content type="html"><![CDATA[<p><a href="https://victorfengming.gitee.io/python/collection/pip-conf">pip配置</a></p><p><a href="http://luyiminggonnabeok.cn/2018/08/10/%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84SSR%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91%E6%A2%AF%E5%AD%90/">十分钟搭建自己的科学上网SSR梯子（自建VPN）</a></p><p><a href="https://jingyan.baidu.com/article/60ccbceb639d2364cab19799.html">禁用笔记本键盘</a></p><p><a href="https://blog.imalan.cn/archives/blog-with-github/">完全使用 GitHub 写博客</a></p><p><a href="https://www.qfgolang.com/">千峰go语言学习网站</a></p><p><a href="https://www.jianshu.com/p/421cc442f06c">GitBook 使用教程</a></p><p><a href="https://book.itxueyuan.com/JbPZ">go语言教程-IT学院</a></p><p><a href="https://www.jianshu.com/p/e323216ce67b">weblogic介绍</a></p><p><a href="https://www.liwenzhou.com/posts/Go/go_menu/">Go语言学习之路</a></p><p><a href="http://c.biancheng.net/golang/intro/">GO介绍-C语言学习网</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> solution </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>基于django的在线教育平台项目01</title>
      <link href="python/Django/gmooc-edu-platform/"/>
      <url>python/Django/gmooc-edu-platform/</url>
      
        <content type="html"><![CDATA[<h1 id="项目地址"><a href="#项目地址" class="headerlink" title="项目地址"></a>项目地址</h1><p>gitee:<a href="https://gitee.com/victorfengming/edu_platform_django">https://gitee.com/victorfengming/edu_platform_django</a></p><h1 id="技术栈"><a href="#技术栈" class="headerlink" title="技术栈"></a>技术栈</h1><p>前台 : vue-cli axios webpack jQuery Bootstrap<br>后台 : python django mysql</p><h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><h3 id="开发环境"><a href="#开发环境" class="headerlink" title="开发环境"></a>开发环境</h3><p>python:  3.7.2<br>Django: 2.2.8</p><h3 id="编辑工具"><a href="#编辑工具" class="headerlink" title="编辑工具"></a>编辑工具</h3><p>pycharm:2019.2<br>sublime text 3<br>Chrome  79.0  </p><h1 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h1><p>在正式开始做项目之前我们需要对项目的需求进行分析,只有需求分析明确了,后面的工作才能水到渠成的进行</p><p>首先这个系统分为两部分,前台和后台:</p><h3 id="前台"><a href="#前台" class="headerlink" title="前台"></a>前台</h3><p>前台系统主要分为四个模块:</p><ul><li>首页</li><li>公开课</li><li>授课教师</li><li>授课机构<h3 id="后台"><a href="#后台" class="headerlink" title="后台"></a>后台</h3>后台管理系统主要分为4个模块</li><li>首页</li><li>权限管理</li><li>教师管理</li><li>公开课管理</li><li>机构管理</li></ul><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://www.cnblogs.com/derek1184405959/p/8590360.html">https://www.cnblogs.com/derek1184405959/p/8590360.html</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django笔记06-auth认证</title>
      <link href="python/Django/note/django-note6/"/>
      <url>python/Django/note/django-note6/</url>
      
        <content type="html"><![CDATA[<p>#auth认证系统的主要组成部分<br><a href="https://docs.djangoproject.com/en/1.11/ref/contrib/auth/">https://docs.djangoproject.com/en/1.11/ref/contrib/auth/</a></p><p>1,用户 </p><p>2,组</p><p>3,权限</p><h2 id="自定义权限认证管理"><a href="#自定义权限认证管理" class="headerlink" title="自定义权限认证管理"></a>自定义权限认证管理</h2><p><a href="https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#custom-permissions">https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#custom-permissions</a></p><h3 id="第一步-自定义权限"><a href="#第一步-自定义权限" class="headerlink" title="第一步  自定义权限"></a>第一步  自定义权限</h3><pre><code>需要在定义模型中 使用 元 选项</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Task</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">...</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">    permissions = (</span><br><span class="line">        (<span class="string">&quot;view_task&quot;</span>, <span class="string">&quot;Can see available tasks&quot;</span>),</span><br><span class="line">        (<span class="string">&quot;change_task_status&quot;</span>, <span class="string">&quot;Can change the status of tasks&quot;</span>),</span><br><span class="line">        (<span class="string">&quot;close_task&quot;</span>, <span class="string">&quot;Can remove a task by setting its status as closed&quot;</span>),</span><br><span class="line">    )</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="第二步-在后台中实现-对管理员和组的管理"><a href="#第二步-在后台中实现-对管理员和组的管理" class="headerlink" title="第二步,在后台中实现 对管理员和组的管理"></a>第二步,在后台中实现 对管理员和组的管理</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">管理员添加</span><br><span class="line">    from django.contrib.auth.models import User</span><br><span class="line">    创建用户</span><br><span class="line">    User.objects.create_user()</span><br><span class="line">    创建超级用户</span><br><span class="line">    User.objects.create_superuser(用户名，电子邮件，密码，** extra_fields)</span><br><span class="line">    https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.11&#x2F;ref&#x2F;contrib&#x2F;auth&#x2F;#django.contrib.auth.models.UserManager.create_user</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    # 判断是否需要为用户分配组 </span><br><span class="line">    gs &#x3D; request.POST.getlist(&#39;gs&#39;,None)</span><br><span class="line">    if gs:</span><br><span class="line">        # 给当前用户分组</span><br><span class="line">        ob.groups.set(gs)</span><br><span class="line">        ob.save()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">组添加</span><br><span class="line"></span><br><span class="line">    # 创建组</span><br><span class="line">    g &#x3D; Group(name&#x3D;request.POST[&#39;name&#39;])</span><br><span class="line">    g.save()</span><br><span class="line"></span><br><span class="line">    #给组添加权限</span><br><span class="line">    https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.11&#x2F;ref&#x2F;contrib&#x2F;auth&#x2F;#group-model</span><br><span class="line"></span><br><span class="line">    # 获取选择的所有权限</span><br><span class="line">    prms  &#x3D; request.POST.getlist(&#39;prms&#39;,None)</span><br><span class="line">    # 判断是否需要给组添加权限</span><br><span class="line">    if prms:</span><br><span class="line">        # 给组分配权限</span><br><span class="line">        g.permissions.set(prms)</span><br><span class="line">        g.save()</span><br><span class="line">    </span><br><span class="line"></span><br><span class="line">权限获取</span><br><span class="line">    # 读取所有权限信息</span><br><span class="line">    # Permission.objects.all()</span><br><span class="line">    # 读取所有权限信息,并排除以Can开头的系统默认生成权限</span><br><span class="line">    perms &#x3D; Permission.objects.exclude(name__istartswith&#x3D;&#39;Can&#39;)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="第三步-进行验证-验证是否登录-验证是否具有权限"><a href="#第三步-进行验证-验证是否登录-验证是否具有权限" class="headerlink" title="第三步,进行验证,验证是否登录,验证是否具有权限"></a>第三步,进行验证,验证是否登录,验证是否具有权限</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">login()  logout()</span><br><span class="line">https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.11&#x2F;topics&#x2F;auth&#x2F;default&#x2F;#how-to-log-a-user-in</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">检查用户是否具有特定权限是相对常见的任务。出于这个原因，Django为这种情况提供了一个快捷方式： permission_required()装饰器：</span><br><span class="line">https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.11&#x2F;topics&#x2F;auth&#x2F;default&#x2F;#the-permission-required-decorator</span><br><span class="line"></span><br><span class="line">使用中间件来验证用户是否登陆</span><br><span class="line"></span><br><span class="line">使用 装饰器 来验证是否具有操作权限</span><br></pre></td></tr></table></figure><h3 id="第四步-在html模板中判断当前登录的用户是否能查看"><a href="#第四步-在html模板中判断当前登录的用户是否能查看" class="headerlink" title="第四步,在html模板中判断当前登录的用户是否能查看"></a>第四步,在html模板中判断当前登录的用户是否能查看</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">在模板中操作权限</span><br><span class="line">https://docs.djangoproject.com/en/1.11/topics/auth/default/#permissions</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> &#123; &#123; perms &#125; &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">     &#123; % if request.user.is_superuser or &#x27;demo.show_users&#x27; in perms % &#125;</span><br><span class="line">         <span class="tag">&lt;<span class="name">li</span>&gt;</span>用户管理<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">     &#123; % endif % &#125;</span><br><span class="line"></span><br><span class="line">     &#123; % if request.user.is_superuser or &#x27;demo.show_types&#x27; in perms % &#125;</span><br><span class="line">         <span class="tag">&lt;<span class="name">li</span>&gt;</span>分类管理<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">     &#123; % endif % &#125;</span><br><span class="line"></span><br><span class="line">     &#123; % if request.user.is_superuser or &#x27;demo.show_goods&#x27; in perms % &#125;</span><br><span class="line">         <span class="tag">&lt;<span class="name">li</span>&gt;</span>商品管理<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">     &#123; % endif % &#125;</span><br><span class="line"> <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>###其他操作</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 获取当前会话的用户对象</span></span><br><span class="line">    obj = get_user(request)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取当前用户拥有的所有权限</span></span><br><span class="line">    pms = obj.get_all_permissions()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 检查当前用户是否具有 perm 权限</span></span><br><span class="line">    <span class="comment"># res = obj.has_perm(&#x27;demo.add_types&#x27;)</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python操作数据库笔记1</title>
      <link href="database/database-python-note1/"/>
      <url>database/database-python-note1/</url>
      
        <content type="html"><![CDATA[<h2 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h2><h3 id="分关系型数据库"><a href="#分关系型数据库" class="headerlink" title="分关系型数据库"></a>分关系型数据库</h3><h4 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h4><ul><li>文档型</li><li>key-value型</li><li>列式数据库</li><li>图形数据库</li></ul><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;张三&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;age&quot;</span>: <span class="number">20</span>,</span><br><span class="line">  <span class="attr">&quot;sex&quot;</span>: <span class="string">&quot;男&quot;</span>,</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;李四&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;age&quot;</span>: <span class="number">18</span>,</span><br><span class="line">  <span class="attr">&quot;sex&quot;</span>: <span class="string">&quot;nv&quot;</span>,</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure><h4 id="文档类型"><a href="#文档类型" class="headerlink" title="文档类型"></a>文档类型</h4><table><thead><tr><th>举例</th><th>CouchDB,MongoDB</th></tr></thead><tbody><tr><td>典型应用场景</td><td>Web应用(与key-vlaue类似,value是结构化的,不同的是数据库能够了解value的内容</td></tr><tr><td>数据模型</td><td>key-value对应的键值对,value为结构化数据</td></tr><tr><td>强项</td><td>查找速度快,可扩展性强,更容易进行分布式扩展</td></tr><tr><td>弱项</td><td>功能相对局限</td></tr></tbody></table><h4 id="key-value型"><a href="#key-value型" class="headerlink" title="key-value型"></a>key-value型</h4><table><thead><tr><th>举例</th><th>Redis,Voldemort,Oracle DBD</th></tr></thead><tbody><tr><td>典型应用场景</td><td>内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等</td></tr><tr><td>数据模型</td><td>key指向value的键值对,通常用hash table来实现</td></tr><tr><td>强项</td><td>查找速度快</td></tr><tr><td>弱项</td><td>数据无结构化,通常只被当做字符串或者二进制数据</td></tr></tbody></table><h4 id="列式数据库"><a href="#列式数据库" class="headerlink" title="列式数据库"></a>列式数据库</h4><table><thead><tr><th>举例</th><th>Cassandra,HBase,Riak</th></tr></thead><tbody><tr><td>典型应用场景</td><td>分布式的文件系统</td></tr><tr><td>数据模型</td><td>以列簇式存储,将同一列数据存在一起</td></tr><tr><td>强项</td><td>查找速度快,可扩展性强,更容易进行分布式扩展</td></tr><tr><td>弱项</td><td>功能相对局限</td></tr></tbody></table><h4 id="图形数据库"><a href="#图形数据库" class="headerlink" title="图形数据库"></a>图形数据库</h4><table><thead><tr><th>举例</th><th>Neo4J,InfoGrid,Infinite Graph</th></tr></thead><tbody><tr><td>典型应用场景</td><td>社交网络,推荐系统等,专注于构建关系图谱图结构</td></tr><tr><td>数据模型</td><td>图结构</td></tr><tr><td>强项</td><td>利用图结构相关算法,比如最短路径寻址,N度关系查找等</td></tr><tr><td>弱项</td><td>很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案</td></tr></tbody></table><h4 id="MYSQL-事务处理主要有两种方法："><a href="#MYSQL-事务处理主要有两种方法：" class="headerlink" title="MYSQL 事务处理主要有两种方法："></a>MYSQL 事务处理主要有两种方法：</h4><p>1、用 BEGIN, ROLLBACK, COMMIT来实现</p><p>BEGIN 开始一个事务<br>ROLLBACK 事务回滚<br>COMMIT 事务确认<br>2、直接用 SET 来改变 MySQL 的自动提交模式:  </p><p>SET AUTOCOMMIT=0 禁止自动提交<br>SET AUTOCOMMIT=1 开启自动提交  </p>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> redis </tag>
            
            <tag> mongodb </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>redis面试题汇总</title>
      <link href="database/redis/redis-interview/"/>
      <url>database/redis/redis-interview/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.w3cschool.cn/redis/redis-ydwp2ozz.html">https://www.w3cschool.cn/redis/redis-ydwp2ozz.html</a></p><h3 id="1、redis是什么？"><a href="#1、redis是什么？" class="headerlink" title="1、redis是什么？"></a>1、redis是什么？</h3><p>　　Redis是一个开源（BSD许可）的，内存中的数据结构存储系统，它可以用作数据库、缓存和消息中间件。  </p><h3 id="2、Redis有什么特点"><a href="#2、Redis有什么特点" class="headerlink" title="2、Redis有什么特点"></a>2、Redis有什么特点</h3><p>　　Redis是一个Key-Value类型的内存数据库，和memcached有点像，整个数据库都是在内存当中进行加载操作，定期通过异步操作把数据库数据flush到硬盘上进行保存。Redis的性能很高，可以处理超过10万次/秒的读写操作，是目前已知性能最快的Key-Value DB。</p><p>　　除了性能外，Redis还支持保存多种数据结构，此外单个value的最大限制是1GB，比memcached的1MB高太多了，因此Redis可以用来实现很多有用的功能，比方说用他的List来做FIFO双向链表，实现一个轻量级的高性 能消息队列服务，用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value设置expire时间，因此也可以被当作一 个功能加强版的memcached来用。</p><p>　　当然，Redis也有缺陷，那就是是数据库容量受到物理内存的限制，不能用作海量数据的高性能读写，因此Redis比较适合那些局限在较小数据量的高性能操作和运算上。</p><h3 id="3-使用redis有哪些好处？"><a href="#3-使用redis有哪些好处？" class="headerlink" title="3.使用redis有哪些好处？"></a>3.使用redis有哪些好处？</h3><p>　　(1) 速度快，因为数据存在内存中，类似于HashMap，HashMap的优势就是查找和操作的时间复杂度都是O(1)<br>　　(2) 支持丰富数据类型，支持string，list，set，sorted set，hash<br>　　(3) 支持事务，操作都是原子性，所谓的原子性就是对数据的更改要么全部执行，要么全部不执行<br>　　(4) 丰富的特性：可用于缓存，消息，按key设置过期时间，过期后将会自动删除</p><h3 id="4-redis相比memcached有哪些优势？"><a href="#4-redis相比memcached有哪些优势？" class="headerlink" title="4.redis相比memcached有哪些优势？"></a>4.redis相比memcached有哪些优势？</h3><p>(1) memcached所有的值均是简单的字符串，redis作为其替代者，支持更为丰富的数据类型<br>(2) redis的速度比memcached快很多<br>(3) redis可以持久化其数据</p><h3 id="5-Memcache与Redis的区别都有哪些？"><a href="#5-Memcache与Redis的区别都有哪些？" class="headerlink" title="5.Memcache与Redis的区别都有哪些？"></a>5.Memcache与Redis的区别都有哪些？</h3><p>　　1)、存储方式 Memecache把数据全部存在内存之中，断电后会挂掉，数据不能超过内存大小。 Redis有部份存在硬盘上，这样能保证数据的持久性。</p><p>　　2)、数据支持类型 Memcache对数据类型支持相对简单。 Redis有复杂的数据类型。</p><p>　　3)、使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己构建了VM 机制 ，因为一般的系统调用系统函数的话，会浪费一定的时间去移动和请求。</p><h3 id="6-redis常见性能问题和解决方案："><a href="#6-redis常见性能问题和解决方案：" class="headerlink" title="6.redis常见性能问题和解决方案："></a>6.redis常见性能问题和解决方案：</h3><p>　　1).Master写内存快照，save命令调度rdbSave函数，会阻塞主线程的工作，当快照比较大时对性能影响是非常大的，会间断性暂停服务，所以Master最好不要写内存快照。</p><p>　　2).Master AOF持久化，如果不重写AOF文件，这个持久化方式对性能的影响是最小的，但是AOF文件会不断增大，AOF文件过大会影响Master重启的恢复速度。Master最好不要做任何持久化工作，包括内存快照和AOF日志文件，特别是不要启用内存快照做持久</p><p>　　化,如果数据比较关键，某个Slave开启AOF备份数据，策略为每秒同步一次。</p><p>　　3).Master调用BGREWRITEAOF重写AOF文件，AOF在重写的时候会占大量的CPU和内存资源，导致服务load过高，出现短暂服务暂停现象。</p><p>　　4). Redis主从复制的性能问题，为了主从复制的速度和连接的稳定性，Slave和Master最好在同一个局域网内</p><h3 id="7-mySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据"><a href="#7-mySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据" class="headerlink" title="7. mySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据"></a>7. mySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据</h3><p>　　相关知识：</p><ul><li><p>redis 内存数据集大小上升到一定大小的时候，就会施行数据淘汰策略（回收策略）。redis 提供 6种数据淘汰策略：</p></li><li><p>volatile-lru：从已设置过期时间的数据集（<code>server.db[i].expires</code>）中挑选最近最少使用的数据淘汰</p></li><li><p>volatile-ttl：从已设置过期时间的数据集（<code>server.db[i].expires</code>）中挑选将要过期的数据淘汰</p></li><li><p>volatile-random：从已设置过期时间的数据集（<code>server.db[i].expires</code>）中任意选择数据淘汰</p></li><li><p>allkeys-lru：从数据集（<code>server.db[i].dict</code>）中挑选最近最少使用的数据淘汰</p></li><li><p>allkeys-random：从数据集（<code>server.db[i].dict</code>）中任意选择数据淘汰</p></li><li><p>no-enviction（驱逐）：禁止驱逐数据</p></li></ul><h3 id="8-请用Redis和任意语言实现一段恶意登录保护的代码"><a href="#8-请用Redis和任意语言实现一段恶意登录保护的代码" class="headerlink" title="8.请用Redis和任意语言实现一段恶意登录保护的代码"></a>8.请用Redis和任意语言实现一段恶意登录保护的代码</h3><p>限制1小时内每用户Id最多只能登录5次。具体登录函数或功能用空函数即可，不用详细写出。</p><p>　　用列表实现:列表中每个元素代表登陆时间,只要最后的第5次登陆时间和现在时间差不超过1小时就禁止登陆.用Python写的代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;!/usr/bin/env python3&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> redis  </span><br><span class="line"><span class="keyword">import</span> sys  </span><br><span class="line"><span class="keyword">import</span> time  </span><br><span class="line"> </span><br><span class="line">r = redis.StrictRedis(host=’<span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>′, port=<span class="number">6379</span>, db=<span class="number">0</span>)  </span><br><span class="line"><span class="keyword">try</span>:       </span><br><span class="line">    <span class="built_in">id</span> = sys.argv[<span class="number">1</span>]</span><br><span class="line"><span class="keyword">except</span>:      </span><br><span class="line">    print(‘<span class="built_in">input</span> argument error’)    </span><br><span class="line">    sys.exit(<span class="number">0</span>)  </span><br><span class="line"><span class="keyword">if</span> r.llen(<span class="built_in">id</span>) &gt;= <span class="number">5</span> <span class="keyword">and</span> time.time() – <span class="built_in">float</span>(r.lindex(<span class="built_in">id</span>, <span class="number">4</span>)) &lt;= <span class="number">3600</span>:      </span><br><span class="line">    print(“you are forbidden logining”)</span><br><span class="line"><span class="keyword">else</span>:       </span><br><span class="line">    print(‘you are allowed to login’)    </span><br><span class="line">    r.lpush(<span class="built_in">id</span>, time.time())    </span><br><span class="line">    <span class="comment"># login_func()</span></span><br></pre></td></tr></table></figure><h3 id="9-为什么redis需要把所有数据放到内存中"><a href="#9-为什么redis需要把所有数据放到内存中" class="headerlink" title="9.为什么redis需要把所有数据放到内存中?"></a>9.为什么redis需要把所有数据放到内存中?</h3><p>　　Redis为了达到最快的读写速度将数据都读到内存中，并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。如果不将数据放在内存中，磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天，redis将会越来越受欢迎。</p><p>　　如果设置了最大使用的内存，则数据已有记录数达到内存限值后不能继续插入新值。</p><h3 id="10-Redis是单进程单线程的"><a href="#10-Redis是单进程单线程的" class="headerlink" title="10.Redis是单进程单线程的"></a>10.Redis是单进程单线程的</h3><p>　　redis利用队列技术将并发访问变为串行访问，消除了传统数据库串行控制的开销</p><h3 id="11-redis的并发竞争问题如何解决"><a href="#11-redis的并发竞争问题如何解决" class="headerlink" title="11.redis的并发竞争问题如何解决?"></a>11.redis的并发竞争问题如何解决?</h3><p>　　Redis为单进程单线程模式，采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念，Redis对于多个客户端连接并不存在竞争，但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题，这些问题均是</p><p>　　由于客户端连接混乱造成。对此有2种解决方法：</p><p>　　1.客户端角度，为保证每个客户端间正常有序与Redis进行通信，对连接进行池化，同时对客户端读写Redis操作采用内部锁synchronized。</p><p>　　2.服务器角度，利用setnx实现锁。</p><p>　　注：对于第一种，需要应用程序自己处理资源的同步，可以使用的方法比较通俗，可以使用synchronized也可以使用lock；第二种需要用到Redis的setnx命令，但是需要注意一些问题。</p><h3 id="12-redis事物的了解CAS-check-and-set-操作实现乐观锁"><a href="#12-redis事物的了解CAS-check-and-set-操作实现乐观锁" class="headerlink" title="12.redis事物的了解CAS(check-and-set 操作实现乐观锁 )?"></a>12.redis事物的了解CAS(check-and-set 操作实现乐观锁 )?</h3><p>　　和众多其它数据库一样，Redis作为NoSQL数据库也同样提供了事务机制。在Redis中，MULTI/EXEC/DISCARD/WATCH这四个命令是我们实现事务的基石。相信对有关系型数据库开发经验的开发者而言这一概念并不陌生，即便如此，我们还是会简要的列出</p><p>　　Redis中</p><p>　　事务的实现特征：</p><p>　　1). 在事务中的所有命令都将会被串行化的顺序执行，事务执行期间，Redis不会再为其它客户端的请求提供任何服务，从而保证了事物中的所有命令被原子的执行。</p><p>　　2). 和关系型数据库中的事务相比，在Redis事务中如果有某一条命令执行失败，其后的命令仍然会被继续执行。</p><p>　　3). 我们可以通过MULTI命令开启一个事务，有关系型数据库开发经验的人可以将其理解为”BEGIN TRANSACTION”语句。在该语句之后执行的命令都将被视为事务之内的操作，最后我们可以通过执行EXEC/DISCARD命令来提交/回滚该事务内的所有操作。这两个Redis命令可被视为等同于关系型数据库中的COMMIT/ROLLBACK语句。</p><p>　　4). 在事务开启之前，如果客户端与服务器之间出现通讯故障并导致网络断开，其后所有待执行的语句都将不会被服务器执行。然而如果网络中断事件是发生在客户端执行EXEC命令之后，那么该事务中的所有命令都会被服务器执行。</p><p>　　5). 当使用Append-Only模式时，Redis会通过调用系统函数write将该事务内的所有写操作在本次调用中全部写入磁盘。然而如果在写入的过程中出现系统崩溃，如电源故障导致的宕机，那么此时也许只有部分数据被写入到磁盘，而另外一部分数据却已经丢失。</p><p>　　Redis服务器会在重新启动时执行一系列必要的一致性检测，一旦发现类似问题，就会立即退出并给出相应的错误提示。此时，我们就要充分利用Redis工具包中提供的redis-check-aof工具，该工具可以帮助我们定位到数据不一致的错误，并将已经写入的部分数据进行回滚。修复之后我们就可以再次重新启动Redis服务器了。</p><h3 id="13-WATCH命令和基于CAS的乐观锁："><a href="#13-WATCH命令和基于CAS的乐观锁：" class="headerlink" title="13.WATCH命令和基于CAS的乐观锁："></a>13.WATCH命令和基于CAS的乐观锁：</h3><p>　　在Redis的事务中，WATCH命令可用于提供CAS(check-and-set)功能。假设我们通过WATCH命令在事务执行之前监控了多个Keys，倘若在WATCH之后有任何Key的值发生了变化，EXEC命令执行的事务都将被放弃，同时返回Null multi-bulk应答以通知调用者事务</p><p>　　执行失败。例如，我们再次假设Redis中并未提供incr命令来完成键值的原子性递增，如果要实现该功能，我们只能自行编写相应的代码。其伪码如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">val &#x3D; GET mykey</span><br><span class="line">val &#x3D; val + 1</span><br><span class="line">SET mykey $val</span><br></pre></td></tr></table></figure><p>以上代码只有在单连接的情况下才可以保证执行结果是正确的，因为如果在同一时刻有多个客户端在同时执行该段代码，那么就会出现多线程程序中经常出现的一种错误场景–竞态争用(race condition)。比如，客户端A和B都在同一时刻读取了mykey的原有值，假设该值为10，此后两个客户端又均将该值加一后set回Redis服务器，这样就会导致mykey的结果为11，而不是我们认为的12。为了解决类似的问题，我们需要借助WATCH命令的帮助，见如下代码：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">WATCH mykey</span><br><span class="line">val &#x3D; GET mykey</span><br><span class="line">val &#x3D; val + 1</span><br><span class="line">MULTI</span><br><span class="line">SET mykey $val</span><br><span class="line">EXEC</span><br></pre></td></tr></table></figure><p>和此前代码不同的是，新代码在获取mykey的值之前先通过WATCH命令监控了该键，此后又将set命令包围在事务中，这样就可以有效的保证每个连接在执行EXEC之前，如果当前连接获取的mykey的值被其它连接的客户端修改，那么当前连接的EXEC命令将执行失败。这样调用者在判断返回值后就可以获悉val是否被重新设置成功。</p><h3 id="14-redis持久化的几种方式"><a href="#14-redis持久化的几种方式" class="headerlink" title="14.redis持久化的几种方式"></a>14.redis持久化的几种方式</h3><h4 id="1、快照（snapshots）"><a href="#1、快照（snapshots）" class="headerlink" title="1、快照（snapshots）"></a>1、快照（snapshots）</h4><p>　　缺省情况情况下，Redis把数据快照存放在磁盘上的二进制文件中，文件名为dump.rdb。你可以配置Redis的持久化策略，例如数据集中每N秒钟有超过M次更新，就将数据写入磁盘；或者你可以手工调用命令SAVE或BGSAVE。</p><p>　　工作原理</p><p>　　． Redis forks.</p><p>　　． 子进程开始将数据写到临时RDB文件中。</p><p>　　． 当子进程完成写RDB文件，用新文件替换老文件。</p><p>　　． 这种方式可以使Redis使用copy-on-write技术。</p><h4 id="2、AOF"><a href="#2、AOF" class="headerlink" title="2、AOF"></a>2、AOF</h4><p>　　快照模式并不十分健壮，当系统停止，或者无意中Redis被kill掉，最后写入Redis的数据就会丢失。这对某些应用也许不是大问题，但对于要求高可靠性的应用来说，</p><p>　　Redis就不是一个合适的选择。</p><p>　　Append-only文件模式是另一种选择。</p><p>　　你可以在配置文件中打开AOF模式</p><h4 id="3、虚拟内存方式"><a href="#3、虚拟内存方式" class="headerlink" title="3、虚拟内存方式"></a>3、虚拟内存方式</h4><p>　　当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.</p><p>　　当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.</p><p>　　vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.</p><p>　　自己测试的时候发现用虚拟内存性能也不错。如果数据量很大，可以考虑分布式或者其他数据库</p><h3 id="15-redis的缓存失效策略和主键失效机制"><a href="#15-redis的缓存失效策略和主键失效机制" class="headerlink" title="15.redis的缓存失效策略和主键失效机制"></a>15.redis的缓存失效策略和主键失效机制</h3><p>　　作为缓存系统都要定期清理无效数据，就需要一个主键失效和淘汰策略.</p><p>　　在Redis当中，有生存期的key被称为volatile。在创建缓存时，要为给定的key设置生存期，当key过期的时候（生存期为0），它可能会被删除。</p><h4 id="1、影响生存时间的一些操作"><a href="#1、影响生存时间的一些操作" class="headerlink" title="1、影响生存时间的一些操作"></a>1、影响生存时间的一些操作</h4><p>　　生存时间可以通过使用 DEL 命令来删除整个 key 来移除，或者被 SET 和 GETSET 命令覆盖原来的数据，也就是说，修改key对应的value和使用另外相同的key和value来覆盖以后，当前数据的生存时间不同。</p><p>　　比如说，对一个 key 执行INCR命令，对一个列表进行LPUSH命令，或者对一个哈希表执行HSET命令，这类操作都不会修改 key 本身的生存时间。另一方面，如果使用RENAME对一个 key 进行改名，那么改名后的 key的生存时间和改名前一样。</p><p>　　RENAME命令的另一种可能是，尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ，这时旧的 another_key (以及它的生存时间)会被删除，然后旧的 key 会改名为 another_key ，因此，新的 another_key 的生存时间也和原本的 key 一样。使用PERSIST命令可以在不删除 key 的情况下，移除 key 的生存时间，让 key 重新成为一个persistent key 。</p><h4 id="2、如何更新生存时间"><a href="#2、如何更新生存时间" class="headerlink" title="2、如何更新生存时间"></a>2、如何更新生存时间</h4><p>　　可以对一个已经带有生存时间的 key 执行EXPIRE命令，新指定的生存时间会取代旧的生存时间。过期时间的精度已经被控制在1ms之内，主键失效的时间复杂度是O（1），</p><p>　　EXPIRE和TTL命令搭配使用，TTL可以查看key的当前生存时间。设置成功返回 1；当 key 不存在或者不能为 key 设置生存时间时，返回 0 。</p><p>　　最大缓存配置</p><p>　　在 redis 中，允许用户设置最大使用内存大小</p><p>　　server.maxmemory</p><p>　　默认为0，没有指定最大缓存，如果有新的数据添加，超过最大内存，则会使redis崩溃，所以一定要设置。redis 内存数据集大小上升到一定大小的时候，就会实行数据淘汰策略。</p><p>　　redis 提供 6种数据淘汰策略：</p><p>　　． volatile-lru：从已设置过期时间的数据集（server.db[i].expires）中挑选最近最少使用的数据淘汰</p><p>　　． volatile-ttl：从已设置过期时间的数据集（server.db[i].expires）中挑选将要过期的数据淘汰</p><p>　　． volatile-random：从已设置过期时间的数据集（server.db[i].expires）中任意选择数据淘汰</p><p>　　． allkeys-lru：从数据集（server.db[i].dict）中挑选最近最少使用的数据淘汰</p><p>　　． allkeys-random：从数据集（server.db[i].dict）中任意选择数据淘汰</p><p>　　． no-enviction（驱逐）：禁止驱逐数据</p><p>　　注意这里的6种机制，volatile和allkeys规定了是对已设置过期时间的数据集淘汰数据还是从全部数据集淘汰数据，后面的lru、ttl以及random是三种不同的淘汰策略，再加上一种no-enviction永不回收的策略。</p><p>　   使用策略规则：</p><p>　　1、如果数据呈现幂律分布，也就是一部分数据访问频率高，一部分数据访问频率低，则使用allkeys-lru</p><p>　　2、如果数据呈现平等分布，也就是所有的数据访问频率都相同，则使用allkeys-random</p><p>　　三种数据淘汰策略：</p><p>　　ttl和random比较容易理解，实现也会比较简单。主要是Lru最近最少使用淘汰策略，设计上会对key 按失效时间排序，然后取最先失效的key进行淘汰。</p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>redis笔记01</title>
      <link href="database/redis/redis-note1/"/>
      <url>database/redis/redis-note1/</url>
      
        <content type="html"><![CDATA[<h2 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h2><h3 id="redis简介"><a href="#redis简介" class="headerlink" title="redis简介"></a>redis简介</h3><p>redis是完全开源免费的,遵守<a href="https://baike.baidu.com/item/BSD%E5%8D%8F%E8%AE%AE">BSD协议</a>,是一个高性能的key-value数据库.</p><h4 id="redis与其他key-value缓存产品有一下三个特点"><a href="#redis与其他key-value缓存产品有一下三个特点" class="headerlink" title="redis与其他key-value缓存产品有一下三个特点:"></a>redis与其他key-value缓存产品有一下三个特点:</h4><ul><li>redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用</li><li>redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储.</li><li>redis支持数据的备份,及master-slave模式的数据备份<h3 id="redis优势"><a href="#redis优势" class="headerlink" title="redis优势"></a>redis优势</h3></li><li>性能极高-Redis能读的速度是110000次/s,写的速度是81000次/s.</li><li>丰富的数据类型-Redis支持二进制案例的Strings,List,Hashes,Sets及Ordered Sets数据类型操作</li><li>原子-redis的所有操作都是原子性的,同时redis还支持对几个操作全并后的<a href="https://blog.csdn.net/qq_30243515/article/details/82557535">原子性</a>执行(原子性即为一个操作的完整性,要不就全不操作,要不就操作成功)</li><li>丰富的特性- Redis还支持<a href="https://jingyan.baidu.com/article/54b6b9c0a6dbdd2d583b4716.html">publish / subscribe</a> ,<a href="https://www.cnblogs.com/tangxuliang/p/10659439.html">通知</a> ,<a href="https://www.cnblogs.com/duhuo/p/6323499.html">key过期</a>的等等特性.</li></ul><h3 id="Redis与其他key-value存储有什么不同"><a href="#Redis与其他key-value存储有什么不同" class="headerlink" title="Redis与其他key-value存储有什么不同?"></a>Redis与其他key-value存储有什么不同?</h3><ul><li>Redis有着更为复杂的数据类型,不用于其他key-value类型的数据库方案,他这个类型更加的透明对于程序员来说,无需进行额外的抽象</li><li>Redis虽然说的运行在内存中,但是也是可以进行持久化存储到硬盘中的,这要根据这个数据量进行权衡.这样相比在硬盘中的复杂的数据类型,内存操作显得更加的直接,简单,这样redis可以做更加复杂的一些操作.同时,在磁盘的格式方面,他们是以一个紧凑的追加方式产生的,因为他们不需要进行随机的访问.</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>redis笔记02</title>
      <link href="database/redis/redis-note2/"/>
      <url>database/redis/redis-note2/</url>
      
        <content type="html"><![CDATA[<h2 id="Redis-安装"><a href="#Redis-安装" class="headerlink" title="Redis 安装"></a>Redis 安装</h2><h3 id="Window-下安装"><a href="#Window-下安装" class="headerlink" title="Window 下安装"></a>Window 下安装</h3><p>下载地址：<a href="https://github.com/dmajkic/redis/downloads%E3%80%82">https://github.com/dmajkic/redis/downloads。</a></p><p>下载到的Redis支持32bit和64bit。根据自己实际情况选择，将64bit的内容cp到自定义盘符安装目录取名redis。 如 C:\redis</p><p>打开一个cmd窗口 使用cd命令切换目录到 C:\redis 运行 redis-server.exe redis.conf 。（如果下载的是Redis-x64-3.2.100版本，是运行 redis-server.exe redis.windows.conf）</p><p>如果想方便的话，可以把redis的路径加到系统的环境变量里，这样就省得再输路径了，后面的那个redis.conf可以省略，如果省略，会启用默认的。</p><p>这时候另启一个cmd窗口，原来的不要关闭，不然就无法访问服务端了。</p><p>切换到redis目录下运行 redis-cli.exe -h 127.0.0.1 -p 6379 。</p><p>设置键值对 set myKey abc</p><p>取出键值对 get myKey</p><h3 id="Ubuntu-下安装"><a href="#Ubuntu-下安装" class="headerlink" title="Ubuntu 下安装"></a>Ubuntu 下安装</h3><p>在 Ubuntu 系统安装 Redi 可以使用以下命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash">sudo apt-get update</span></span><br><span class="line"><span class="meta">$</span><span class="bash">sudo apt-get install redis-server</span></span><br></pre></td></tr></table></figure><p>启动 Redis</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$redis-server</span><br></pre></td></tr></table></figure><p>查看 redis 是否启动？</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$redis-cli</span><br></pre></td></tr></table></figure><p>以上命令将打开以下终端：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt;</span><br></pre></td></tr></table></figure><p>127.0.0.1 是本机 IP ，6379 是 redis 服务端口。现在我们输入 PING 命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; ping</span><br><span class="line">PONG</span><br></pre></td></tr></table></figure><p>以上说明我们已经成功安装了redis。</p><h2 id="Redis-配置"><a href="#Redis-配置" class="headerlink" title="Redis 配置"></a>Redis 配置</h2><p>Redis 的配置文件位于 Redis 安装目录下，文件名为 redis.conf。</p><p>你可以通过 CONFIG 命令查看或设置配置项。</p><h3 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h3><p>Redis CONFIG 命令格式如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; CONFIG GET CONFIG_SETTING_NAME</span><br></pre></td></tr></table></figure><h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; CONFIG GET loglevel</span><br><span class="line"></span><br><span class="line">1) &quot;loglevel&quot;</span><br><span class="line">2) &quot;notice&quot;</span><br></pre></td></tr></table></figure><p>使用 * 号获取所有配置项：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; CONFIG GET *</span><br><span class="line"> 1) &quot;dir&quot;</span><br><span class="line"> 2) &quot;C:\\Users\\Administrator&quot;</span><br><span class="line"> 3) &quot;dbfilename&quot;</span><br><span class="line"> 4) &quot;dump.rdb&quot;</span><br><span class="line"> 5) &quot;requirepass&quot;</span><br><span class="line"> 6) (nil)</span><br><span class="line"> 7) &quot;masterauth&quot;</span><br><span class="line"> 8) (nil)</span><br><span class="line"> 9) &quot;maxmemory&quot;</span><br><span class="line">10) &quot;0&quot;</span><br><span class="line">11) &quot;maxmemory-policy&quot;</span><br><span class="line">12) &quot;volatile-lru&quot;</span><br><span class="line">13) &quot;maxmemory-samples&quot;</span><br><span class="line">14) &quot;3&quot;</span><br><span class="line">15) &quot;timeout&quot;</span><br><span class="line">16) &quot;0&quot;</span><br><span class="line">17) &quot;appendonly&quot;</span><br><span class="line">18) &quot;no&quot;</span><br><span class="line">19) &quot;no-appendfsync-on-rewrite&quot;</span><br><span class="line">20) &quot;no&quot;</span><br><span class="line">21) &quot;appendfsync&quot;</span><br><span class="line">22) &quot;everysec&quot;</span><br><span class="line">23) &quot;save&quot;</span><br><span class="line">24) &quot;3600 1 300 100 60 10000&quot;</span><br><span class="line">25) &quot;auto-aof-rewrite-percentage&quot;</span><br><span class="line">26) &quot;100&quot;</span><br><span class="line">27) &quot;auto-aof-rewrite-min-size&quot;</span><br><span class="line">28) &quot;1048576&quot;</span><br><span class="line">29) &quot;slave-serve-stale-data&quot;</span><br><span class="line">30) &quot;yes&quot;</span><br><span class="line">31) &quot;hash-max-zipmap-entries&quot;</span><br><span class="line">32) &quot;512&quot;</span><br><span class="line">33) &quot;hash-max-zipmap-value&quot;</span><br><span class="line">34) &quot;64&quot;</span><br><span class="line">35) &quot;list-max-ziplist-entries&quot;</span><br><span class="line">36) &quot;512&quot;</span><br><span class="line">37) &quot;list-max-ziplist-value&quot;</span><br><span class="line">38) &quot;64&quot;</span><br><span class="line">39) &quot;set-max-intset-entries&quot;</span><br><span class="line">40) &quot;512&quot;</span><br><span class="line">41) &quot;zset-max-ziplist-entries&quot;</span><br><span class="line">42) &quot;128&quot;</span><br><span class="line">43) &quot;zset-max-ziplist-value&quot;</span><br><span class="line">44) &quot;64&quot;</span><br><span class="line">45) &quot;slowlog-log-slower-than&quot;</span><br><span class="line">46) &quot;10000&quot;</span><br><span class="line">47) &quot;slowlog-max-len&quot;</span><br><span class="line">48) &quot;64&quot;</span><br><span class="line">49) &quot;loglevel&quot;</span><br><span class="line">50) &quot;verbose&quot;</span><br></pre></td></tr></table></figure><h3 id="编辑配置"><a href="#编辑配置" class="headerlink" title="编辑配置"></a>编辑配置</h3><p>你可以通过修改 redis.conf 文件或使用 CONFIG set 命令来修改配置。</p><h3 id="语法-1"><a href="#语法-1" class="headerlink" title="语法"></a>语法</h3><p><code>CONFIG SET</code> 命令基本语法：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE</span><br></pre></td></tr></table></figure><h3 id="实例-1"><a href="#实例-1" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; CONFIG SET loglevel &quot;notice&quot;</span><br><span class="line">OK</span><br><span class="line">redis 127.0.0.1:6379&gt; CONFIG GET loglevel</span><br><span class="line"></span><br><span class="line">1) &quot;loglevel&quot;</span><br><span class="line">2) &quot;notice&quot;</span><br></pre></td></tr></table></figure><h3 id="参数说明"><a href="#参数说明" class="headerlink" title="参数说明"></a>参数说明</h3><p>参数说明<br>redis.conf 配置项说明如下：</p><ol><li><p>Redis默认不是以守护进程的方式运行，可以通过该配置项修改，使用yes启用守护进程</p><p> <code>daemonize no</code></p></li><li><p>当Redis以守护进程方式运行时，Redis默认会把pid写入/var/run/redis.pid文件，可以通过pidfile指定</p><p><code> pidfile /var/run/redis.pid</code></p></li><li><p>指定Redis监听端口，默认端口为6379，作者在自己的一篇博文中解释了为什么选用6379作为默认端口，因为6379在手机按键上MERZ对应的号码，而MERZ取自意大利歌女Alessia Merz的名字</p><p> <code>port 6379</code></p></li><li><p>绑定的主机地址</p><p> <code>bind 127.0.0.1</code></p></li><li><p>当 客户端闲置多长时间后关闭连接，如果指定为0，表示关闭该功能</p><p> <code>timeout 300</code></p></li><li><p>指定日志记录级别，Redis总共支持四个级别：debug、verbose、notice、warning，默认为verbose</p><p> <code>loglevel verbose</code></p></li><li><p>日志记录方式，默认为标准输出，如果配置Redis为守护进程方式运行，而这里又配置为日志记录方式为标准输出，则日志将会发送给/dev/null</p><p> <code>logfile stdout</code></p></li><li><p>设置数据库的数量，默认数据库为0，可以使用SELECT <dbid>命令在连接上指定数据库id</p><p> <code>databases 16</code></p></li><li><p>指定在多长时间内，有多少次更新操作，就将数据同步到数据文件，可以多个条件配合</p><p><code> save &lt;seconds&gt; &lt;changes&gt;</code></p><p> Redis默认配置文件中提供了三个条件：</p><p> <code>save 900 1</code></p><p> <code>save 300 10</code></p><p> <code>save 60 10000</code></p><p> 分别表示900秒（15分钟）内有1个更改，300秒（5分钟）内有10个更改以及60秒内有10000个更改。</p></li><li><p>指定存储至本地数据库时是否压缩数据，默认为yes，Redis采用LZF压缩，如果为了节省CPU时间，可以关闭该选项，但会导致数据库文件变的巨大</p><p><code>rdbcompression yes</code></p></li><li><p>指定本地数据库文件名，默认值为dump.rdb</p><p><code>dbfilename dump.rdb</code></p></li><li><p>指定本地数据库存放目录</p><p><code>dir ./</code></p></li><li><p>设置当本机为slav服务时，设置master服务的IP地址及端口，在Redis启动时，它会自动从master进行数据同步</p><p><code>slaveof &lt;masterip&gt; &lt;masterport&gt;</code></p></li><li><p>当master服务设置了密码保护时，slav服务连接master的密码</p><p><code>masterauth &lt;master-password&gt;</code></p></li><li><p>设置Redis连接密码，如果配置了连接密码，客户端在连接Redis时需要通过AUTH <password>命令提供密码，默认关闭</p><p><code>requirepass foobared</code></p></li><li><p>设置同一时间最大客户端连接数，默认无限制，Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数，如果设置 maxclients 0，表示不作限制。当客户端连接数到达限制时，Redis会关闭新的连接并向客户端返回max number of clients reached错误信息</p><p><code>maxclients 128</code></p></li><li><p>指定Redis最大内存限制，Redis在启动时会把数据加载到内存中，达到最大内存后，Redis会先尝试清除已到期或即将到期的Key，当此方法处理 后，仍然到达最大内存设置，将无法再进行写入操作，但仍然可以进行读取操作。Redis新的vm机制，会把Key存放内存，Value会存放在swap区</p><p><code>maxmemory &lt;bytes&gt;</code></p></li><li><p>指定是否在每次更新操作后进行日志记录，Redis在默认情况下是异步的把数据写入磁盘，如果不开启，可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的，所以有的数据会在一段时间内只存在于内存中。默认为no</p><p><code>appendonly no</code></p></li><li><p>指定更新日志文件名，默认为appendonly.aof</p><p> <code>appendfilename appendonly.aof</code></p></li><li><p>指定更新日志条件，共有3个可选值：<br>no：表示等操作系统进行数据缓存同步到磁盘（快）<br>always：表示每次更新操作后手动调用fsync()将数据写到磁盘（慢，安全）<br>everysec：表示每秒同步一次（折衷，默认值）</p><p><code>appendfsync everysec</code></p></li><li><p>指定是否启用虚拟内存机制，默认值为no，简单的介绍一下，VM机制将数据分页存放，由Redis将访问量较少的页即冷数据swap到磁盘上，访问多的页面由磁盘自动换出到内存中（在后面的文章我会仔细分析Redis的VM机制）</p><p> <code>vm-enabled no</code></p></li><li><p>虚拟内存文件路径，默认值为/tmp/redis.swap，不可多个Redis实例共享</p><p><code> vm-swap-file /tmp/redis.swap</code></p></li><li><p>将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0</p><p> <code>vm-max-memory 0</code></p></li><li><p>Redis swap文件分成了很多的page，一个对象可以保存在多个page上面，但一个page上不能被多个对象共享，vm-page-size是要根据存储的 数据大小来设定的，作者建议如果存储很多小对象，page大小最好设置为32或者64bytes；如果存储很大大对象，则可以使用更大的page，如果不 确定，就使用默认值</p><p> <code>vm-page-size 32</code></p></li><li><p>设置swap文件中的page数量，由于页表（一种表示页面空闲或使用的bitmap）是在放在内存中的，，在磁盘上每8个pages将消耗1byte的内存。</p><p> <code>vm-pages 134217728</code></p></li><li><p>设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的，可能会造成比较长时间的延迟。默认值为4</p><p> <code>vm-max-threads 4</code></p></li><li><p>设置在向客户端应答时，是否把较小的包合并为一个包发送，默认为开启</p><p><code>glueoutputbuf yes</code></p></li><li><p>指定在超过一定的数量或者最大的元素超过某一临界值时，采用一种特殊的哈希算法</p><p><code>hash-max-zipmap-entries 6</code>4</p><p><code>hash-max-zipmap-value 51</code>2</p></li><li><p>指定是否激活重置哈希，默认为开启（后面在介绍Redis的哈希算法时具体介绍）</p><p><code>activerehashing yes</code></p></li><li><p>指定包含其它的配置文件，可以在同一主机上多个Redis实例之间使用同一份配置文件，而同时各个实例又拥有自己的特定配置文件</p><p><code>include /path/to/local.conf</code></p></li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>redis笔记03</title>
      <link href="database/redis/redis-note3/"/>
      <url>database/redis/redis-note3/</url>
      
        <content type="html"><![CDATA[<h2 id="Redis数据类型"><a href="#Redis数据类型" class="headerlink" title="Redis数据类型"></a>Redis数据类型</h2><h3 id="Redis-数据类型"><a href="#Redis-数据类型" class="headerlink" title="Redis 数据类型"></a>Redis 数据类型</h3><p>redis支持种数据类型 : </p><ul><li>string(字符串)</li><li>hash(哈希)</li><li>list(列表)</li><li>set(集合)</li><li>zset(sorted set:有序集合)</li></ul><h3 id="String（字符串）"><a href="#String（字符串）" class="headerlink" title="String（字符串）"></a>String（字符串）</h3><p>string是redis最基本的类型，你可以理解成与<a href="https://www.runoob.com/memcached/memcached-tutorial.html">Memcached</a>一模一样的类型，一个key对应一个value。</p><p>string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。</p><p>string类型是Redis最基本的数据类型，一个键最大能存储512MB。</p><h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; set name &quot;victor&quot;</span><br><span class="line">OK</span><br><span class="line">redis 127.0.0.1:6379&gt; get name</span><br><span class="line">&quot;victor&quot;</span><br></pre></td></tr></table></figure><p>在以上实例中我们使用了 Redis 的 SET 和 GET 命令。键为 name，对应的值为”victor”</p><p>注意：一个键最大能存储512MB。</p><h3 id="Hash（哈希）"><a href="#Hash（哈希）" class="headerlink" title="Hash（哈希）"></a>Hash（哈希）</h3><p>Redis hash 是一个键值对集合。</p><p>Redis hash是一个string类型的field和value的映射表，hash特别适合用于存储对象。</p><h3 id="实例-1"><a href="#实例-1" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; hmset user:1 username victor password 123456 points 200</span><br><span class="line">OK</span><br><span class="line">redis 127.0.0.1:6379&gt; hgetall user:1</span><br><span class="line">1) &quot;username&quot;</span><br><span class="line">2) &quot;victor&quot;</span><br><span class="line">3) &quot;password&quot;</span><br><span class="line">4) &quot;123456&quot;</span><br><span class="line">5) &quot;points&quot;</span><br><span class="line">6) &quot;200&quot;</span><br></pre></td></tr></table></figure><p>以上实例中 hash 数据类型存储了包含用户脚本信息的用户对象。实例中我们使用了 Redis HMSET, HGETALL 命令，user:1 为键值。</p><p>每个 hash 可以存储 2^32 - 1 键值对（40多亿）。</p><h3 id="List（列表）"><a href="#List（列表）" class="headerlink" title="List（列表）"></a>List（列表）</h3><p>Redis 列表是简单的字符串列表，按照插入顺序排序。你可以添加一个元素到列表的头部（左边）或者尾部（右边）。</p><h3 id="实例-2"><a href="#实例-2" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; lpush mylist python</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; lpush mylist java</span><br><span class="line">(integer) 2</span><br><span class="line">redis 127.0.0.1:6379&gt; lpush mylist php</span><br><span class="line">(integer) 3</span><br><span class="line">redis 127.0.0.1:6379&gt; lpush mylist node</span><br><span class="line">(integer) 4</span><br><span class="line">redis 127.0.0.1:6379&gt; lrange mylist 0 11</span><br><span class="line">1) &quot;node&quot;</span><br><span class="line">2) &quot;php&quot;</span><br><span class="line">3) &quot;java&quot;</span><br><span class="line">4) &quot;python&quot;</span><br><span class="line">redis 127.0.0.1:6379&gt;</span><br></pre></td></tr></table></figure><p>列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。</p><h3 id="Set（集合）"><a href="#Set（集合）" class="headerlink" title="Set（集合）"></a>Set（集合）</h3><p>Redis的Set是string类型的无序集合。</p><p>集合是通过哈希表实现的，所以添加，删除，查找的复杂度都是O(1)。</p><h3 id="sadd-命令"><a href="#sadd-命令" class="headerlink" title="sadd 命令"></a>sadd 命令</h3><p>添加一个string元素到,key对应的set集合中，成功返回1,如果元素以及在集合中返回0,key对应的set不存在返回错误。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sadd key member</span><br></pre></td></tr></table></figure><h3 id="实例-3"><a href="#实例-3" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; sadd list1 ttk</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; sadd list1 victor</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; sadd list1 nineberg</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; sadd list1 mengya</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; sadd list1 yupeng</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; sadd list1 chenzan</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; smembers list1</span><br><span class="line">1) &quot;mengya&quot;</span><br><span class="line">2) &quot;nineberg&quot;</span><br><span class="line">3) &quot;ttk&quot;</span><br><span class="line">4) &quot;chenzan&quot;</span><br><span class="line">5) &quot;victor&quot;</span><br><span class="line">6) &quot;yupeng&quot;</span><br><span class="line">redis 127.0.0.1:6379&gt; sadd list1 yupeng</span><br><span class="line">(integer) 0</span><br><span class="line">redis 127.0.0.1:6379&gt; smembers list1 yupeng</span><br><span class="line">(error) ERR wrong number of arguments for &#39;smembers&#39; command</span><br><span class="line">redis 127.0.0.1:6379&gt; smembers list1</span><br><span class="line">1) &quot;nineberg&quot;</span><br><span class="line">2) &quot;ttk&quot;</span><br><span class="line">3) &quot;chenzan&quot;</span><br><span class="line">4) &quot;victor&quot;</span><br><span class="line">5) &quot;yupeng&quot;</span><br><span class="line">6) &quot;mengya&quot;</span><br><span class="line">redis 127.0.0.1:6379&gt;</span><br></pre></td></tr></table></figure><p>注意：以上实例中 rabitmq 添加了两次，但根据集合内元素的唯一性，第二次插入的元素将被忽略。</p><p>集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。</p><h3 id="zset-sorted-set：有序集合"><a href="#zset-sorted-set：有序集合" class="headerlink" title="zset(sorted set：有序集合)"></a>zset(sorted set：有序集合)</h3><p>Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。<br>不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。</p><p>zset的成员是唯一的,但分数(score)却可以重复。</p><h3 id="zadd-命令"><a href="#zadd-命令" class="headerlink" title="zadd 命令"></a>zadd 命令</h3><p>添加元素到集合，元素在集合中存在则更新对应score</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zadd key score member </span><br></pre></td></tr></table></figure><h3 id="实力"><a href="#实力" class="headerlink" title="实力"></a>实力</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; zadd list2 0 node</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; zadd list2 0 html</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; zadd list2 0 css</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; zadd list2 0 js</span><br><span class="line">(integer) 1</span><br><span class="line">redis 127.0.0.1:6379&gt; zadd list2 0 js</span><br><span class="line">(integer) 0</span><br><span class="line">redis 127.0.0.1:6379&gt; zrengebyscore list2 0 1000</span><br><span class="line">(error) ERR unknown command &#39;zrengebyscore&#39;</span><br><span class="line">redis 127.0.0.1:6379&gt; zrangebyscore list2 0 1000</span><br><span class="line">1) &quot;css&quot;</span><br><span class="line">2) &quot;html&quot;</span><br><span class="line">3) &quot;js&quot;</span><br><span class="line">4) &quot;node&quot;</span><br><span class="line">redis 127.0.0.1:6379&gt;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>redis笔记04</title>
      <link href="database/redis/redis-note4/"/>
      <url>database/redis/redis-note4/</url>
      
        <content type="html"><![CDATA[<h2 id="Redis-数据备份与恢复"><a href="#Redis-数据备份与恢复" class="headerlink" title="Redis 数据备份与恢复"></a>Redis 数据备份与恢复</h2><p>Redis SAVE 命令用于创建当前数据库的备份。</p><h3 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h3><p>redis Save 命令基本语法如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; SAVE </span><br></pre></td></tr></table></figure><h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; SAVE </span><br><span class="line">OK</span><br></pre></td></tr></table></figure><p>该命令将在 redis 安装目录中创建<code>dump.rdb</code>文件。</p><h3 id="恢复数据"><a href="#恢复数据" class="headerlink" title="恢复数据"></a>恢复数据</h3><p>如果需要恢复数据，只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取 redis 目录可以使用 CONFIG 命令，如下所示：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">redis 127.0.0.1:6379&gt; CONFIG GET dir</span><br><span class="line">1) &quot;dir&quot;</span><br><span class="line">2) &quot;&#x2F;usr&#x2F;local&#x2F;redis&#x2F;bin&quot;</span><br></pre></td></tr></table></figure><p>以上命令 CONFIG GET dir 输出的 redis 安装目录为 /usr/local/redis/bin。</p><h3 id="Bgsave"><a href="#Bgsave" class="headerlink" title="Bgsave"></a>Bgsave</h3><p>创建 redis 备份文件也可以使用命令 BGSAVE，该命令在后台执行。</p><h3 id="实例-1"><a href="#实例-1" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; BGSAVE</span><br><span class="line">Background saving started</span><br></pre></td></tr></table></figure><h2 id="Redis-安全"><a href="#Redis-安全" class="headerlink" title="Redis 安全"></a>Redis 安全</h2><p>我们可以通过 redis 的配置文件设置密码参数，这样客户端连接到 redis 服务就需要密码验证，这样可以让你的 redis 服务更安全。</p><h3 id="实例-2"><a href="#实例-2" class="headerlink" title="实例"></a>实例</h3><p>我们可以通过以下命令查看是否设置了密码验证：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; CONFIG get requirepass</span><br><span class="line"></span><br><span class="line">1) &quot;requirepass&quot;</span><br><span class="line">2) &quot;&quot;</span><br></pre></td></tr></table></figure><p>默认情况下 requirepass 参数是空的，这就意味着你无需通过密码验证就可以连接到 redis 服务。</p><p>你可以通过以下命令来修改该参数：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; CONFIG set requirepass &quot;w3cschool.cn&quot;</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; CONFIG get requirepass</span><br><span class="line">1) &quot;requirepass&quot;</span><br><span class="line">2) &quot;w3cschool.cn&quot;</span><br></pre></td></tr></table></figure><p>设置密码后，客户端连接 redis 服务就需要密码验证，否则无法执行命令。</p><h3 id="语法-1"><a href="#语法-1" class="headerlink" title="语法"></a>语法</h3><p>AUTH 命令基本语法格式如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; AUTH password</span><br></pre></td></tr></table></figure><h3 id="实例-3"><a href="#实例-3" class="headerlink" title="实例"></a>实例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; AUTH &quot;w3cschool.cn&quot;</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; SET mykey &quot;Test value&quot;</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; GET mykey</span><br><span class="line">&quot;Test value&quot;</span><br></pre></td></tr></table></figure><h2 id="Redis-客户端连接"><a href="#Redis-客户端连接" class="headerlink" title="Redis 客户端连接"></a>Redis 客户端连接</h2><p>Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自客户端的连接，当一个连接建立后，Redis 内部会进行以下一些操作：</p><ul><li>首先，客户端 socket 会被设置为非阻塞模式，因为 Redis 在网络事件处理上采用的是非阻塞多路复用模型。</li><li>然后为这个 socket 设置 TCP_NODELAY 属性，禁用 Nagle 算法</li><li>然后创建一个可读的文件事件用于监听这个客户端 socket 的数据发送</li></ul><h2 id="redis管道技术"><a href="#redis管道技术" class="headerlink" title="redis管道技术"></a>redis管道技术</h2><p>redis管道技术可以在服务端未响应时,客户端可以继续想服务端发送请求,并最终一次性读取所有服务端的响应</p><h3 id="实例-4"><a href="#实例-4" class="headerlink" title="实例"></a>实例</h3><p>查看redis管道,只需要启动redis实例并输入以下命令:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">$(echo -en &quot;PING\r\n SET w3ckey redis\r\nGET w3ckey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n&quot;; sleep 10) | nc localhost 6379</span><br><span class="line"></span><br><span class="line">+PONG</span><br><span class="line">+OK</span><br><span class="line">redis</span><br><span class="line">:1</span><br><span class="line">:2</span><br><span class="line">:3</span><br></pre></td></tr></table></figure><p>以上实例中我们通过使用PING命令查看redis服务是否可用,之后我们设置了w3ckey的值尾redis.然后我们获取w3ckey的值并使得visitor自增3次.<br>在返回的结果中我们可以看到这些命令一次性向redis服务提交,并最终一次性读取所有服务端的响应</p><h3 id="管道技术的优势"><a href="#管道技术的优势" class="headerlink" title="管道技术的优势"></a>管道技术的优势</h3><p>管道技术最显著的优势是提高了redis服务的性能</p><h3 id="一些测试数据"><a href="#一些测试数据" class="headerlink" title="一些测试数据"></a>一些测试数据</h3><p>在下面的测试中,我们将使用redis的Ruby客户端,支持管道技术特性,测试管道技术对速度的提升效果</p><p>从处于局域网中的Mac OS X系统上执行上面这个简单脚本的数据表明，开启了管道操作后，往返时延已经被改善得相当低了。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">without pipelining 1.185238 seconds </span><br><span class="line">with pipelining 0.250783 seconds</span><br></pre></td></tr></table></figure><p>如你所见，开启管道后，我们的速度效率提升了5倍。</p><h2 id="redis-分区"><a href="#redis-分区" class="headerlink" title="redis 分区"></a>redis 分区</h2><p>分区是分割数据到多个redis实例的处理过程,因此每个实例只保存key的一个子集.</p><h3 id="分区的优势"><a href="#分区的优势" class="headerlink" title="分区的优势"></a>分区的优势</h3><ul><li>通过利用多台计算机内存的和值,允许我们构造跟大的数据库</li><li>通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,扩展网络带宽</li></ul><h3 id="分区的不足"><a href="#分区的不足" class="headerlink" title="分区的不足"></a>分区的不足</h3><p>redis的一些特性在分区方面表现的不是很好:</p><ul><li>涉及多个key的操作通常是不被支持的.举例来说,当两个set映射到不同的redis实例时,你就补鞥呢对这两个set执行交集操作.</li><li>涉及多个key和redis事务不能使用</li><li>当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个主机备份持久化文件</li><li>增加或者删除容量也比较复杂.redis集群大多数支持在运行时增加,删除节点的透明数据平衡的能力,但是类似于客户端分区,代理等其他系统则不支持这项特性.然而,一种叫做presharding的技术对此是有帮助的.</li></ul><h3 id="分区类型"><a href="#分区类型" class="headerlink" title="分区类型"></a>分区类型</h3><p>redis 有两种类型的分区.假设有4个redis实例,R0,R1,R2,R3 和类似user:1,user:2这样的表示用户的多个key,对既定的key有多种不同方式来选择这个key存放在哪个实例中,也就是说,有不同的系统来映射某个key到某个redis服务</p><h3 id="范围分区"><a href="#范围分区" class="headerlink" title="范围分区"></a>范围分区</h3><p>最简单的分区方式是安范围分区,就是映射一定范围的对象到特定的redis实例<br>比如,id从0到10000的用户会保存到实例R0,ID从10001到 20000的用户会保存到R1，以此类推。</p><p>这种方式是可行的，并且在实际中使用，不足就是要有一个区间范围到实例的映射表。这个表要被管理，同时还需要各 种对象的映射表，通常对Redis来说并非是好的方法。</p><h3 id="哈希分区"><a href="#哈希分区" class="headerlink" title="哈希分区"></a>哈希分区</h3><p>另外一种分区方法是hash分区。这对任何key都适用，也无需是object_name:这种形式，像下面描述的一样简单：</p><ul><li>用一个hash函数将key转换为一个数字，比如使用crc32 hash函数。对key foobar执行crc32(foobar)会输出类似93024922的整数。</li><li>对这个整数取模，将其转化为0-3之间的数字，就可以将这个整数映射到4个Redis实例中的一个了。93024922 % 4 = 2，就是说key foobar应该被存到R2实例中。注意：取模操作是取除的余数，通常在多种编程语言中用%操作符实现。</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue.js前后端分离2</title>
      <link href="front/vue/old/vue-note2/"/>
      <url>front/vue/old/vue-note2/</url>
      
        <content type="html"><![CDATA[<h3 id="内容回顾"><a href="#内容回顾" class="headerlink" title="内容回顾"></a>内容回顾</h3><h4 id="过滤器"><a href="#过滤器" class="headerlink" title="- 过滤器"></a>- 过滤器</h4><h5 id="局部的过滤器"><a href="#局部的过滤器" class="headerlink" title="- 局部的过滤器"></a>- 局部的过滤器</h5><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 只能在当前组件内部使用</span></span><br><span class="line">filters:<span class="function"><span class="keyword">function</span>(<span class="params">val,a,b</span>)</span>&#123;</span><br><span class="line">    <span class="comment">// 执行过滤处理逻辑,(添油加醋的内容)</span></span><br><span class="line">    <span class="keyword">return</span> xxx;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h5 id="全局的过滤器"><a href="#全局的过滤器" class="headerlink" title="- 全局的过滤器"></a>- 全局的过滤器</h5><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 声明+创建 在任何组件中都能使用</span></span><br><span class="line">Vue.filter(<span class="string">&quot;myTime&quot;</span>,<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 添油加醋的处理</span></span><br><span class="line">    <span class="keyword">return</span> xxxx;                </span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><h4 id="生命周期-钩子函数"><a href="#生命周期-钩子函数" class="headerlink" title="- 生命周期-钩子函数"></a>- 生命周期-钩子函数</h4><ul><li>beforeCreate这个方法不常用  </li><li>create 组件创建完成,<ul><li>可以发起ajax(XMLHTTPRequest 简称 XHR axios fetch $.ajax())请求</li><li>实现数据驱动视图思想</li></ul></li><li>beforeMount 挂载</li><li>mounted DOM挂载完成    </li><li>beforeUpdate 获取原始的DOM</li><li>updated 后去更新之后的DOM</li><li>beforeDestroy 组件销毁之前</li><li>destroyed 组件销毁之后</li><li>actived 激活当前组件 Vue提供的内置组件<code>&lt;keep-alive&gt;&lt;/keep-alive&gt;</code></li><li>deactivated 停用当前组件<h3 id="vue-router-核心插件"><a href="#vue-router-核心插件" class="headerlink" title="vue-router 核心插件"></a>vue-router 核心插件</h3><h4 id="主要作用-实现单页面应用-为了用户体验-后端资源过多-可能会出现白屏的现象"><a href="#主要作用-实现单页面应用-为了用户体验-后端资源过多-可能会出现白屏的现象" class="headerlink" title="主要作用: 实现单页面应用,为了用户体验,后端资源过多,可能会出现白屏的现象"></a>主要作用: 实现单页面应用,为了用户体验,后端资源过多,可能会出现白屏的现象</h4>现在都用前后端分离,甚至现在有些后端里面的前后台管理都分离了<h4 id="模板引擎"><a href="#模板引擎" class="headerlink" title="模板引擎:"></a>模板引擎:</h4>node.js express web服务器框架 jade html ejs</li></ul><p>python django   jinja2衍生出来的</p><p>一般后台语言都有一个模板引擎的东东</p><p>{ {  } }</p><p>{ % % }</p><h3 id="模板引擎-VS-前后端分离"><a href="#模板引擎-VS-前后端分离" class="headerlink" title="模板引擎 VS 前后端分离"></a>模板引擎 VS 前后端分离</h3><h4 id="模板引擎的"><a href="#模板引擎的" class="headerlink" title="模板引擎的"></a>模板引擎的</h4><p>好处:减少DOM操作,你一玩dom就不用谢js的dom操作了<br>不好处:随着你的项目越来越大,你的项目在后期不易维护</p><p>当你的需求频繁改的时候,你还得写一些js代码,这样你就模板语法和js混合着写了<br>要是用这种前后端分离的写法,前端专门就搞这个DOM操作,那就厉害了</p><p>等咱们讲完前后端分离,就会发现还是前后端分离好用</p><h4 id="前后端分离"><a href="#前后端分离" class="headerlink" title="前后端分离"></a>前后端分离</h4><p>分工明确</p><p>前端只做前端的事情(页面+交互+兼容+class+封装+优化)</p><ul><li>vue+vue+router+axios+element+ui 前端技术栈<br>后端只做后端的事情(接口(表的操作+业务逻辑+封装+class+优化))</li><li>restframework框架+django+sqlite+redis 后端技术栈</li></ul><p>你写简历的时候可以把这个技术栈列出来</p><ol><li><p>xxx在线教育平台</p></li><li><p>xxx后台管理系统</p></li></ol><p>名字 项目周期 技术栈 项目介绍 项目总结</p><h2 id="vue-router"><a href="#vue-router" class="headerlink" title="vue router"></a>vue router</h2><h3 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h3><p>这里我们直接用CDN的</p><h3 id="引包"><a href="#引包" class="headerlink" title="引包"></a>引包</h3><p>vue-router依赖vue<br><code>vue-router.js</code><br><code>Vue.component(&#39;router-link&#39;,&#123;&#125;)</code><br><code>router-link router-view</code></p><h3 id="如果是模块化机制"><a href="#如果是模块化机制" class="headerlink" title="如果是模块化机制"></a>如果是模块化机制</h3><p>Vue.use(vue-router)</p><h3 id="创建实例"><a href="#创建实例" class="headerlink" title="创建实例"></a>创建实例</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">let</span> Home = &#123;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">        这里就不多些了        </span></span><br><span class="line"><span class="comment">    */</span>        </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> VueRouter(&#123;</span><br><span class="line">    <span class="comment">// 5. 配置路由信息</span></span><br><span class="line">    routes:[</span><br><span class="line">        &#123;</span><br><span class="line">            path:<span class="string">&quot;/&quot;</span>,</span><br><span class="line">            redirect:<span class="string">&quot;/home&quot;</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            path:<span class="string">&quot;/home&quot;</span>,</span><br><span class="line">            name:<span class="string">&quot;/Home&quot;</span>,</span><br><span class="line">            component:Home,</span><br><span class="line">        &#125;,</span><br><span class="line">    ]                   </span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">    <span class="comment">//6. 挂载router对象到vue的实例中</span></span><br><span class="line">    router        </span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><h3 id="使用路由"><a href="#使用路由" class="headerlink" title="使用路由"></a>使用路由</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment">router-link默认被渲染成a标签 to 属性就会被渲染成href了</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">--&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/&quot;</span>&gt;</span>首页<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span>    </span><br><span class="line">    <span class="comment">&lt;!--这个router-link就是我们自定义标签,然后我们换了一个名字,叫组件--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">:to</span>=<span class="string">&quot;/home&quot;</span> @<span class="attr">click.native</span> = <span class="string">&quot;&quot;</span>&gt;</span>首页<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span>    </span><br><span class="line">    路由组件的出口    </span><br><span class="line">    <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span>    </span><br><span class="line">        </span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="动态路由匹配"><a href="#动态路由匹配" class="headerlink" title="动态路由匹配"></a>动态路由匹配</h3><p><code>/user/1</code>    <code>/user/2</code> 加载的是同一个组件</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">routes:[</span><br><span class="line">    &#123;</span><br><span class="line">        path:<span class="string">&quot;/&quot;</span>,</span><br><span class="line">        redirect:<span class="string">&quot;/home&quot;</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        path:<span class="string">&quot;/user/:id&quot;</span>,</span><br><span class="line">        name:<span class="string">&quot;/User&quot;</span>,</span><br><span class="line">        component:User,</span><br><span class="line">    &#125;,</span><br><span class="line">]               </span><br></pre></td></tr></table></figure><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;&#123;name:&#x27;User&#x27;,params:&#123;xxx:&#x27;front&#x27;&#125;&#125;&quot;</span>&gt;</span>前端<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span>    </span><br><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;&#123;name:&#x27;User&#x27;,params:&#123;xxx:&#x27;ios&#x27;&#125;&#125;&quot;</span>&gt;</span>IOS<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span>    </span><br></pre></td></tr></table></figure><p>复用的组件 ,监听路由的变化</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">watch:<span class="function">(<span class="params">to,<span class="keyword">from</span></span>)=&gt;</span>&#123;</span><br><span class="line">    to 要进入的页面的路由信息对象</span><br><span class="line">    <span class="keyword">from</span> 从哪个    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="编程式导航"><a href="#编程式导航" class="headerlink" title="编程式导航"></a>编程式导航</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">this</span>.$router.push(&#123;</span><br><span class="line">    name:<span class="string">&quot;Home&quot;</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>vue-router 提供的内置的内容</p><p><code>router-link</code></p><p><code>router-view</code></p><p><code>this.$route</code> 路由信息对象</p><p><code>this.$router</code> 路由对象</p><h2 id="今日内容"><a href="#今日内容" class="headerlink" title="今日内容"></a>今日内容</h2><h3 id="获取原生的DOM的方式"><a href="#获取原生的DOM的方式" class="headerlink" title="获取原生的DOM的方式"></a>获取原生的DOM的方式</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">ref</span> = <span class="string">&quot;alex&quot;</span>&gt;</span>哈哈哈<span class="tag">&lt;/<span class="name">div</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">ref</span>=<span class="string">&quot;a&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">Home</span> <span class="attr">ref</span>=<span class="string">&quot;b&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">Home</span>&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">this</span>.$refs.alex</span><br></pre></td></tr></table></figure><h3 id="DIY脚手架"><a href="#DIY脚手架" class="headerlink" title="DIY脚手架"></a>DIY脚手架</h3><p>下一个东西<br>脚手架不要下最新的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i webpack@3.12.0 -g</span><br></pre></td></tr></table></figure><p>cmd<br>module.exports = xxx<br>require()<br>es6module</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> a <span class="keyword">from</span> <span class="string">&quot;./main.js&quot;</span></span><br></pre></td></tr></table></figure><h3 id="vue-cli的使用"><a href="#vue-cli的使用" class="headerlink" title="vue-cli的使用"></a>vue-cli的使用</h3><h3 id="webpack"><a href="#webpack" class="headerlink" title="webpack"></a>webpack</h3><p>组件化开发vue-cli</p><p>webpack 前端中的工具 ,三大主流工具 之 最主流的</p><p>grunt gulp webpack</p><p>目前webpack已经占据了主流市场<br>webpack是一个现代JavaScript应用程序的静态模块打包器.当webpack处理应用程序时,它会递归地构建一个依赖关系,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle</p><p>所有的后端都支持模块化</p><p>但是我们的前端是不支持模块化的</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
            <tag> django </tag>
            
            <tag> axios </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue.js前后端分离3</title>
      <link href="front/vue/old/vue-note3/"/>
      <url>front/vue/old/vue-note3/</url>
      
        <content type="html"><![CDATA[<p><a href="https://www.cnblogs.com/derek1184405959/p/8590360.html">Django+xadmin打造在线教育平台（一）</a></p><p><a href="https://blog.csdn.net/linfeng886/article/details/85800540">Cli3工具中，配置路径别名</a></p><p><a href="https://blog.csdn.net/yun_hou/article/details/86530164">vue-cli 3.0 中 vue.config.js 配置路径别名</a></p><p><a href="https://www.cnblogs.com/dancer0321/p/10477065.html">vue动态绑定src加字符串拼接</a></p><p><a href="https://www.jianshu.com/p/91409ab30dc7">Django 模型 ImageField 字段的使用</a></p><p><a href="https://blog.csdn.net/qq_16687863/article/details/98597300">Vue请求Django后台获取图片资源</a></p><p><a href="https://blog.csdn.net/qq_24551305/article/details/84882635">运行django项目指定IP和端口</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
            <tag> django </tag>
            
            <tag> axios </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>axios浅析</title>
      <link href="front/vue/old/axios/"/>
      <url>front/vue/old/axios/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.jianshu.com/p/df464b26ae58">https://www.jianshu.com/p/df464b26ae58</a></p><article class="_2rhmJa">    <h2>一、安装</h2>    <p>1、 利用npm安装<code>npm install axios --save</code><br>        2、 利用bower安装<code>bower install axios --save</code><br>        3、 直接利用cdn引入<code>&lt;script src="https://unpkg.com/axios/dist/axios.min.js"&gt;&lt;/script&gt;</code></p>    <h2>二、例子</h2>    <p>1、 发送一个<code>GET</code>请求</p>    <div class="_2Uzcx_">        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy">            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true">                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>            </svg>        </i></button>        <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span                class="token comment">//通过给定的ID来发送请求</span>axios<span class="token punctuation">.</span><span class="token function">get</span><span                    class="token punctuation">(</span><span class="token string">'/user?ID=12345'</span><span                    class="token punctuation">)</span>  <span class="token punctuation">.</span><span class="token function">then</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token parameter">response</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>response<span class="token punctuation">)</span><span                    class="token punctuation">;</span>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>  <span class="token punctuation">.</span><span class="token function">catch</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token parameter">err</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>err<span class="token punctuation">)</span><span                    class="token punctuation">;</span>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span                    class="token punctuation">;</span><span class="token comment">//以上请求也可以通过这种方式来发送</span>axios<span class="token punctuation">.</span><span class="token function">get</span><span                    class="token punctuation">(</span><span class="token string">'/user'</span><span                    class="token punctuation">,</span><span class="token punctuation">&#123;</span>  params<span class="token punctuation">:</span><span class="token punctuation">&#123;</span>    <span class="token constant">ID</span><span class="token punctuation">:</span><span                    class="token number">12345</span>  <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">response</span><span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span                    class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token parameter">err</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span                    class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>    </div>    <p>2、 发送一个<code>POST</code>请求</p>    <div class="_2Uzcx_">        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy">            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true">                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>            </svg>        </i></button>        <pre class="line-numbers  language-jsx"><code class="  language-jsx">axios<span                class="token punctuation">.</span><span class="token function">post</span><span                class="token punctuation">(</span><span class="token string">'/user'</span><span                class="token punctuation">,</span><span class="token punctuation">&#123;</span>  firstName<span class="token punctuation">:</span><span class="token string">'Fred'</span><span                    class="token punctuation">,</span>  lastName<span class="token punctuation">:</span><span class="token string">'Flintstone'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">res</span><span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span                    class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token parameter">err</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span                    class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>    </div>    <p>3、 一次性并发多个请求</p>    <div class="_2Uzcx_">        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy">            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true">                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>            </svg>        </i></button>        <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span                class="token keyword">function</span> <span class="token function">getUserAccount</span><span                class="token punctuation">(</span><span class="token punctuation">)</span><span                class="token punctuation">&#123;</span>  <span class="token keyword">return</span> axios<span class="token punctuation">.</span><span class="token function">get</span><span                    class="token punctuation">(</span><span class="token string">'/user/12345'</span><span                    class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token keyword">function</span> <span class="token function">getUserPermissions</span><span                    class="token punctuation">(</span><span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span>  <span class="token keyword">return</span> axios<span class="token punctuation">.</span><span class="token function">get</span><span                    class="token punctuation">(</span><span                    class="token string">'/user/12345/permissions'</span><span                    class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span>axios<span class="token punctuation">.</span><span class="token function">all</span><span                    class="token punctuation">(</span><span class="token punctuation">[</span><span                    class="token function">getUserAccount</span><span class="token punctuation">(</span><span                    class="token punctuation">)</span><span class="token punctuation">,</span><span                    class="token function">getUserPermissions</span><span class="token punctuation">(</span><span                    class="token punctuation">)</span><span class="token punctuation">]</span><span                    class="token punctuation">)</span>  <span class="token punctuation">.</span><span class="token function">then</span><span                    class="token punctuation">(</span>axios<span class="token punctuation">.</span><span                    class="token function">spread</span><span class="token punctuation">(</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">acct<span class="token punctuation">,</span>perms</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span>    <span class="token comment">//当这两个请求都完成的时候会触发这个函数，两个参数分别代表返回的结果</span>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span                    class="token punctuation">)</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>    </div>    <h2>三、axios的API</h2>    <h4>（一） axios可以通过配置（<code>config</code>）来发送请求</h4>    <p>1、 <code>axios(config)</code></p>    <div class="_2Uzcx_">        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy">            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true">                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>            </svg>        </i></button>        <pre class="line-numbers  language-kotlin"><code class="  language-kotlin"><span class="token comment">//发送一个`POST`请求</span><span class="token function">axios</span><span class="token punctuation">(</span><span                    class="token punctuation">&#123;</span>    method<span class="token operator">:</span><span class="token string">"POST"</span><span                    class="token punctuation">,</span>    url<span class="token operator">:</span><span class="token string">'/user/12345'</span><span                    class="token punctuation">,</span>    <span class="token keyword">data</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>        firstName<span class="token operator">:</span><span class="token string">"Fred"</span><span                    class="token punctuation">,</span>        lastName<span class="token operator">:</span><span class="token string">"Flintstone"</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>    </div>    <p>2、 <code>axios(url[,config])</code></p>    <div class="_2Uzcx_">        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy">            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true">                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>            </svg>        </i></button>        <pre class="line-numbers  language-csharp"><code class="  language-csharp"><span class="token comment">//发送一个`GET`请求（默认的请求方式）</span><span class="token function">axios</span><span class="token punctuation">(</span><span class="token string">'/user/12345'</span><span                    class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>    </div>    <h4>（二）、 请求方式的别名，这里对所有已经支持的请求方式都提供了方便的别名</h4>    <div class="_2Uzcx_">        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy">            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true">                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>            </svg>        </i></button>        <pre class="line-numbers  language-css"><code class="  language-css">axios.<span                class="token function">request</span><span                class="token punctuation">(</span>config<span class="token punctuation">)</span><span                class="token punctuation">;</span><p>axios.<span class="token function">get</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>config]<span class="token punctuation">)</span><span                    class="token punctuation">;</span></p><p>axios.<span class="token function">delete</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>config]<span class="token punctuation">)</span><span                    class="token punctuation">;</span></p><p>axios.<span class="token function">head</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>config]<span class="token punctuation">)</span><span                    class="token punctuation">;</span></p><p>axios.<span class="token function">post</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>data[<span class="token punctuation">,</span>config]]<span                    class="token punctuation">)</span><span class="token punctuation">;</span></p><p>axios.<span class="token function">put</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>data[<span class="token punctuation">,</span>config]]<span                    class="token punctuation">)</span></p><p>axios.<span class="token function">patch</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>data[<span class="token punctuation">,</span>config]]<span                    class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <ul><br>        <li>注意：当我们在使用别名方法的时候，<code>url,method,data</code>这几个参数不需要在配置中声明</li><br>    </ul><br>    <h4>（三）、 并发请求（concurrency）,即是帮助处理并发请求的辅助函数</h4><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-cpp"><code class="  language-cpp"><span class="token comment">//iterable是一个可以迭代的参数如数组等</span><br>axios<span class="token punctuation">.</span><span class="token function">all</span><span                    class="token punctuation">(</span>iterable<span class="token punctuation">)</span><br><span class="token comment">//callback要等到所有请求都完成才会执行</span><br>axios<span class="token punctuation">.</span><span class="token function">spread</span><span                    class="token punctuation">(</span>callback<span class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <h4>（四）、创建一个<code>axios</code>实例，并且可以自定义其配置</h4><br>    <p>1、 <code>axios.create([config])</code></p><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-csharp"><code class="  language-csharp"><span                class="token keyword">var</span> instance <span class="token operator">=</span> axios<span                class="token punctuation">.</span><span class="token function">create</span><span                class="token punctuation">(</span><span class="token punctuation">&#123;</span><br>  baseURL<span class="token punctuation">:</span><span class="token string">"<a href="https://some-domain.com/api/&quot;">https://some-domain.com/api/&quot;</a></span><span                    class="token punctuation">,</span><br>  timeout<span class="token punctuation">:</span><span class="token number">1000</span><span                    class="token punctuation">,</span><br>  headers<span class="token punctuation">:</span> <span class="token punctuation">&#123;</span><span class="token string">'X-Custom-Header'</span><span                    class="token punctuation">:</span><span class="token string">'foobar'</span><span                    class="token punctuation">&#125;</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <p>2、 实例的方法</p><br>    <ul><br>        <li>一下是实例方法，注意已经定义的配置将和利用create创建的实例的配置合并</li><br>    </ul><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-css"><code class="  language-css">axios#<span                class="token function">request</span><span                class="token punctuation">(</span>config<span class="token punctuation">)</span></p><p>axios#<span class="token function">get</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>config]<span class="token punctuation">)</span></p><p>axios#<span class="token function">delete</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>config]<span class="token punctuation">)</span></p><p>axios#<span class="token function">head</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>config]<span class="token punctuation">)</span></p><p>axios#<span class="token function">post</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>data[<span class="token punctuation">,</span>config]]<span                    class="token punctuation">)</span></p><p>axios#<span class="token function">put</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>data[<span class="token punctuation">,</span>config]]<span                    class="token punctuation">)</span></p><p>axios#<span class="token function">patch</span><span class="token punctuation">(</span>url[<span                    class="token punctuation">,</span>data[<span class="token punctuation">,</span>config]]<span                    class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <h2>四、请求的配置（request config）</h2><br>    <ul><br>        <li>以下就是请求的配置选项，只有<code>url</code>选项是必须的，如果<code>method</code>选项未定义，那么它默认是以<code>GET</code>的方式发出请求</li><br>    </ul><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span                class="token punctuation">&#123;</span><br>  <span class="token comment">//<code>url</code>是请求的服务器地址</span><br>  url<span class="token punctuation">:</span><span class="token string">'/user'</span><span                    class="token punctuation">,</span><br>  <span class="token comment">//<code>method</code>是请求资源的方式</span><br>  method<span class="token punctuation">:</span><span class="token string">'get'</span><span class="token comment">//default</span><br>  <span class="token comment">//如果<code>url</code>不是绝对地址，那么<code>baseURL</code>将会加到<code>url</code>的前面</span><br>  <span class="token comment">//当<code>url</code>是相对地址的时候，设置<code>baseURL</code>会非常的方便</span><br>  baseURL<span class="token punctuation">:</span><span class="token string">'<a href="https://some-domain.com/api/&#39;">https://some-domain.com/api/&#39;</a></span><span                    class="token punctuation">,</span><br>  <span class="token comment">//<code>transformRequest</code>选项允许我们在请求发送到服务器之前对请求的数据做出一些改动</span><br>  <span class="token comment">//该选项只适用于以下请求方式：<code>put/post/patch</code></span><br>  <span class="token comment">//数组里面的最后一个函数必须返回一个字符串、-一个<code>ArrayBuffer</code>或者<code>Stream</code></span><br>  transformRequest<span class="token punctuation">:</span><span class="token punctuation">[</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">data</span><span class="token punctuation">)</span><span                    class="token punctuation">{</span><br>    <span class="token comment">//在这里根据自己的需求改变数据</span><br>    <span class="token keyword">return</span> data<span class="token punctuation">;</span><br>  <span class="token punctuation">}</span><span class="token punctuation">]</span><span                    class="token punctuation">,</span><br>  <span class="token comment">//<code>transformResponse</code>选项允许我们在数据传送到<code>then/catch</code>方法之前对数据进行改动</span><br>  transformResponse<span class="token punctuation">:</span><span class="token punctuation">[</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">data</span><span class="token punctuation">)</span><span                    class="token punctuation">{</span><br>    <span class="token comment">//在这里根据自己的需求改变数据</span><br>    <span class="token keyword">return</span> data<span class="token punctuation">;</span><br>  <span class="token punctuation">}</span><span class="token punctuation">]</span><span                    class="token punctuation">,</span><br>  <span class="token comment">//<code>headers</code>选项是需要被发送的自定义请求头信息</span><br>  headers<span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">'X-Requested-With'</span><span                    class="token punctuation">:</span><span class="token string">'XMLHttpRequest'</span><span                    class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//<code>params</code>选项是要随请求一起发送的请求参数----一般链接在URL后面</span><br>  <span class="token comment">//他的类型必须是一个纯对象或者是URLSearchParams对象</span><br>  params<span class="token punctuation">:</span> <span class="token punctuation">{</span><br>    <span class="token constant">ID</span><span class="token punctuation">:</span><span                    class="token number">12345</span><br>  <span class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//<code>paramsSerializer</code>是一个可选的函数，起作用是让参数（params）序列化</span><br>  <span class="token comment">//例如(<a href="https://www.npmjs.com/package/qs,http://api.jquery.com/jquery.param">https://www.npmjs.com/package/qs,http://api.jquery.com/jquery.param</a>)</span><br>  <span class="token function-variable function">paramsSerializer</span><span class="token punctuation">:</span> <span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">params</span><span class="token punctuation">)</span><span                    class="token punctuation">{</span><br>    <span class="token keyword">return</span> Qs<span class="token punctuation">.</span><span class="token function">stringify</span><span                    class="token punctuation">(</span>params<span class="token punctuation">,</span><span                    class="token punctuation">{</span>arrayFormat<span class="token punctuation">:</span><span                    class="token string">'brackets'</span><span class="token punctuation">}</span><span                    class="token punctuation">)</span><br>  <span class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//<code>data</code>选项是作为一个请求体而需要被发送的数据</span><br>  <span class="token comment">//该选项只适用于方法：<code>put/post/patch</code></span><br>  <span class="token comment">//当没有设置<code>transformRequest</code>选项时dada必须是以下几种类型之一</span><br>  <span class="token comment">//string/plain/object/ArrayBuffer/ArrayBufferView/URLSearchParams</span><br>  <span class="token comment">//仅仅浏览器：FormData/File/Bold</span><br>  <span class="token comment">//仅node:Stream</span><br>  data <span class="token punctuation">{</span><br>    firstName<span class="token punctuation">:</span><span class="token string">"Fred"</span><br>  <span class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//<code>timeout</code>选项定义了请求发出的延迟毫秒数</span><br>  <span class="token comment">//如果请求花费的时间超过延迟的时间，那么请求会被终止</span></p><p>  timeout<span class="token punctuation">:</span><span class="token number">1000</span><span                    class="token punctuation">,</span><br>  <span class="token comment">//<code>withCredentails</code>选项表明了是否是跨域请求</span></p><p>  withCredentials<span class="token punctuation">:</span><span class="token boolean">false</span><span                    class="token punctuation">,</span><span class="token comment">//default</span><br>  <span class="token comment">//<code>adapter</code>适配器选项允许自定义处理请求，这会使得测试变得方便</span><br>  <span class="token comment">//返回一个promise,并提供验证返回</span><br>  <span class="token function-variable function">adapter</span><span class="token punctuation">:</span> <span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">config</span><span class="token punctuation">)</span><span                    class="token punctuation">{</span><br>    <span class="token comment">/<em>……….</em>/</span><br>  <span class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//<code>auth</code>表明HTTP基础的认证应该被使用，并提供证书</span><br>  <span class="token comment">//这会设置一个authorization头（header）,并覆盖你在header设置的Authorization头信息</span><br>  auth<span class="token punctuation">:</span> <span class="token punctuation">{</span><br>    username<span class="token punctuation">:</span><span class="token string">“zhangsan”</span><span                    class="token punctuation">,</span><br>    password<span class="token punctuation">:</span> <span class="token string">“s00sdkf”</span><br>  <span class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//返回数据的格式</span><br>  <span class="token comment">//其可选项是arraybuffer,blob,document,json,text,stream</span><br>  responseType<span class="token punctuation">:</span><span class="token string">‘json’</span><span                    class="token punctuation">,</span><span class="token comment">//default</span><br>  <span class="token comment">//</span><br>  xsrfCookieName<span class="token punctuation">:</span> <span class="token string">‘XSRF-TOKEN’</span><span                    class="token punctuation">,</span><span class="token comment">//default</span><br>  xsrfHeaderName<span class="token punctuation">:</span><span class="token string">‘X-XSRF-TOKEN’</span><span                    class="token punctuation">,</span><span class="token comment">//default</span><br>  <span class="token comment">//<code>onUploadProgress</code>上传进度事件</span><br>  <span class="token function-variable function">onUploadProgress</span><span class="token punctuation">:</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">progressEvent</span><span class="token punctuation">)</span><span                    class="token punctuation">{</span><br>    <span class="token comment">//下载进度的事件</span><br><span class="token function-variable function">onDownloadProgress</span><span class="token punctuation">:</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">progressEvent</span><span class="token punctuation">)</span><span                    class="token punctuation">{</span><br><span class="token punctuation">}</span><br>  <span class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//相应内容的最大值</span><br>  maxContentLength<span class="token punctuation">:</span><span class="token number">2000</span><span                    class="token punctuation">,</span><br>  <span class="token comment">//<code>validateStatus</code>定义了是否根据http相应状态码，来resolve或者reject promise</span><br>  <span class="token comment">//如果<code>validateStatus</code>返回true(或者设置为<code>null</code>或者<code>undefined</code>),那么promise的状态将会是resolved,否则其状态就是rejected</span><br>  <span class="token function-variable function">validateStatus</span><span class="token punctuation">:</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">status</span><span class="token punctuation">)</span><span                    class="token punctuation">{</span><br>    <span class="token keyword">return</span> status <span class="token operator">&gt;=</span> <span                    class="token number">200</span> <span class="token operator">&amp;&amp;</span> status <span                    class="token operator">&lt;</span><span class="token number">300</span><span                    class="token punctuation">;</span><span class="token comment">//default</span><br>  <span class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//<code>maxRedirects</code>定义了在nodejs中重定向的最大数量</span><br>  maxRedirects<span class="token punctuation">:</span> <span class="token number">5</span><span                    class="token punctuation">,</span><span class="token comment">//default</span><br>  <span class="token comment">//<code>httpAgent/httpsAgent</code>定义了当发送http/https请求要用到的自定义代理</span><br>  <span class="token comment">//keeyAlive在选项中没有被默认激活</span><br>  httpAgent<span class="token punctuation">:</span> <span class="token keyword">new</span> <span                    class="token class-name">http<span class="token punctuation">.</span>Agent</span><span                    class="token punctuation">(</span><span class="token punctuation">{</span>keeyAlive<span                    class="token punctuation">:</span><span class="token boolean">true</span><span                    class="token punctuation">}</span><span class="token punctuation">)</span><span                    class="token punctuation">,</span><br>  httpsAgent<span class="token punctuation">:</span> <span class="token keyword">new</span> <span                    class="token class-name">https<span class="token punctuation">.</span>Agent</span><span                    class="token punctuation">(</span><span class="token punctuation">{</span>keeyAlive<span                    class="token punctuation">:</span><span class="token boolean">true</span><span                    class="token punctuation">}</span><span class="token punctuation">)</span><span                    class="token punctuation">,</span><br>  <span class="token comment">//proxy定义了主机名字和端口号，</span><br>  <span class="token comment">//<code>auth</code>表明http基本认证应该与proxy代理链接，并提供证书</span><br>  <span class="token comment">//这将会设置一个<code>Proxy-Authorization</code> header,并且会覆盖掉已经存在的<code>Proxy-Authorization</code>  header</span><br>  proxy<span class="token punctuation">:</span> <span class="token punctuation">{</span><br>    host<span class="token punctuation">:</span><span class="token string">‘127.0.0.1’</span><span                    class="token punctuation">,</span><br>    port<span class="token punctuation">:</span> <span class="token number">9000</span><span                    class="token punctuation">,</span><br>    auth<span class="token punctuation">:</span> <span class="token punctuation">{</span><br>      username<span class="token punctuation">:</span><span class="token string">‘skda’</span><span                    class="token punctuation">,</span><br>      password<span class="token punctuation">:</span><span class="token string">‘radsd’</span><br>    <span class="token punctuation">}</span><br>  <span class="token punctuation">}</span><span class="token punctuation">,</span><br>  <span class="token comment">//<code>cancelToken</code>定义了一个用于取消请求的cancel token</span><br>  <span class="token comment">//详见cancelation部分</span><br>  cancelToken<span class="token punctuation">:</span> <span class="token keyword">new</span> <span                    class="token class-name">cancelToken</span><span class="token punctuation">(</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">cancel</span><span class="token punctuation">)</span><span                    class="token punctuation">{</span></p><p>  <span class="token punctuation">}</span><span class="token punctuation">)</span><br><span class="token punctuation">}</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <h2>五、请求返回的内容</h2><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-kotlin"><code class="  language-kotlin"><span                class="token punctuation">&#123;</span></p><p>  <span class="token keyword">data</span><span class="token operator">:</span><span                    class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span                    class="token punctuation">,</span><br>  status<span class="token operator">:</span><span class="token number">200</span><span                    class="token punctuation">,</span><br>  <span class="token comment">//从服务器返回的http状态文本</span><br>  statusText<span class="token operator">:</span><span class="token string">‘OK’</span><span                    class="token punctuation">,</span><br>  <span class="token comment">//响应头信息</span><br>  headers<span class="token operator">:</span> <span class="token punctuation">&#123;</span><span                    class="token punctuation">&#125;</span><span class="token punctuation">,</span><br>  <span class="token comment">//<code>config</code>是在请求的时候的一些配置信息</span><br>  config<span class="token operator">:</span> <span class="token punctuation">{</span><span                    class="token punctuation">}</span><br><span class="token punctuation">}</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <ul><br>        <li>你可以这样来获取响应信息</li><br>    </ul><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-jsx"><code class="  language-jsx">axios<span                class="token punctuation">.</span><span class="token function">get</span><span                class="token punctuation">(</span><span class="token string">'/user/12345'</span><span                class="token punctuation">)</span><br>  <span class="token punctuation">.</span><span class="token function">then</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token parameter">res</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>res<span class="token punctuation">.</span>data<span                    class="token punctuation">)</span><span class="token punctuation">;</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>res<span class="token punctuation">.</span>status<span                    class="token punctuation">)</span><span class="token punctuation">;</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>res<span class="token punctuation">.</span>statusText<span                    class="token punctuation">)</span><span class="token punctuation">;</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>res<span class="token punctuation">.</span>headers<span                    class="token punctuation">)</span><span class="token punctuation">;</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>res<span class="token punctuation">.</span>config<span                    class="token punctuation">)</span><span class="token punctuation">;</span><br>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <h2>六、默认配置</h2><br>    <ul><br>        <li>你可以设置默认配置，对所有请求都有效</li><br>    </ul><br>    <p>1、 全局默认配置</p><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-rust"><code class="  language-rust">axios<span                class="token punctuation">.</span>defaults<span                class="token punctuation">.</span>baseURL <span class="token operator">=</span> <span                class="token lifetime-annotation symbol">'<a href="http://api.exmple.com/">http://api.exmple.com</a></span><span                class="token lifetime-annotation symbol">';</span><br>axios<span class="token punctuation">.</span>defaults<span class="token punctuation">.</span>headers<span                    class="token punctuation">.</span>common<span class="token punctuation">[</span><span                    class="token lifetime-annotation symbol">'Authorization</span><span                    class="token lifetime-annotation symbol">']</span> <span                    class="token operator">=</span> AUTH_TOKEN<span                    class="token punctuation">;</span><br>axios<span class="token punctuation">.</span>defaults<span class="token punctuation">.</span>headers<span                    class="token punctuation">.</span>post<span class="token punctuation">[</span><span                    class="token lifetime-annotation symbol">'content-Type</span><span                    class="token lifetime-annotation symbol">']</span> <span class="token operator">=</span> <span                    class="token lifetime-annotation symbol">'appliction/x-www-form-urlencoded</span><span                    class="token lifetime-annotation symbol">';</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <p>2、 自定义的实例默认设置</p><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-csharp"><code class="  language-csharp"><span class="token comment">//当创建实例的时候配置默认配置</span><br><span class="token keyword">var</span> instance <span class="token operator">=</span> axios<span                    class="token punctuation">.</span><span class="token function">create</span><span                    class="token punctuation">(</span><span class="token punctuation">&#123;</span><br>    baseURL<span class="token punctuation">:</span> <span class="token string">'<a href="https://api.example.com&/#39;">https://api.example.com&#39;</a></span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><p><span class="token comment">//当实例创建时候修改配置</span><br>instance<span class="token punctuation">.</span>defaults<span class="token punctuation">.</span>headers<span                    class="token punctuation">.</span>common<span class="token punctuation">[</span><span                    class="token string">“Authorization”</span><span class="token punctuation">]</span> <span                    class="token operator">=</span> AUTH_TOKEN<span class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <p>3、 配置中的有优先级</p><br>    <ul><br>        <li>config配置将会以优先级别来合并，顺序是lib/defauts.js中的默认配置，然后是实例中的默认配置，最后是请求中的config参数的配置，越往后等级越高，后面的会覆盖前面的例子。</li><br>    </ul><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-csharp"><code class="  language-csharp"><span class="token comment">//创建一个实例的时候会使用libray目录中的默认配置</span><br><span class="token comment">//在这里timeout配置的值为0，来自于libray的默认值</span><br><span class="token keyword">var</span> instance <span class="token operator">=</span> axios<span                    class="token punctuation">.</span><span class="token function">create</span><span                    class="token punctuation">(</span><span class="token punctuation">)</span><span                    class="token punctuation">;</span><br><span class="token comment">//回覆盖掉library的默认值</span><br><span class="token comment">//现在所有的请求都要等2.5S之后才会发出</span><br>instance<span class="token punctuation">.</span>defaults<span class="token punctuation">.</span>timeout <span                    class="token operator">=</span> <span class="token number">2500</span><span                    class="token punctuation">;</span><br><span class="token comment">//这里的timeout回覆盖之前的2.5S变成5s</span><br>instance<span class="token punctuation">.</span><span class="token keyword">get</span><span                    class="token punctuation">(</span><span class="token string">'/longRequest'</span><span                    class="token punctuation">,</span><span class="token punctuation">&#123;</span><br>  timeout<span class="token punctuation">:</span> <span class="token number">5000</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <h2>七、拦截器</h2><br>    <ul><br>        <li>你可以在请求、响应在到达<code>then/catch</code>之前拦截他们</li><br>    </ul><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span                class="token comment">//添加一个请求拦截器</span><br>axios<span class="token punctuation">.</span>interceptors<span class="token punctuation">.</span>request<span                    class="token punctuation">.</span><span class="token function">use</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token parameter">config</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span><br>  <span class="token comment">//在请求发出之前进行一些操作</span><br>  <span class="token keyword">return</span> config<span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">err</span><span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span><br>  <span class="token comment">//Do something with request error</span><br>  <span class="token keyword">return</span> Promise<span class="token punctuation">.</span><span class="token function">reject</span><span                    class="token punctuation">(</span>error<span class="token punctuation">)</span><span                    class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token comment">//添加一个响应拦截器</span><br>axios<span class="token punctuation">.</span>interceptors<span class="token punctuation">.</span>response<span                    class="token punctuation">.</span><span class="token function">use</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token parameter">res</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span><br>  <span class="token comment">//在这里对返回的数据进行处理</span><br>  <span class="token keyword">return</span> res<span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">err</span><span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span><br>  <span class="token comment">//Do something with response error</span><br>  <span class="token keyword">return</span> Promise<span class="token punctuation">.</span><span class="token function">reject</span><span                    class="token punctuation">(</span>error<span class="token punctuation">)</span><span                    class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span></p><p><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <p>2、取消拦截器</p><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token keyword">var</span> myInterceptor <span                class="token operator">=</span> axios<span class="token punctuation">.</span>interceptor<span                class="token punctuation">.</span>request<span class="token punctuation">.</span><span                class="token function">use</span><span class="token punctuation">(</span><span                class="token keyword">function</span><span class="token punctuation">(</span><span                class="token punctuation">)</span><span class="token punctuation">&#123;</span><span                class="token comment">/<em>....</em>/</span><span class="token punctuation">&#125;</span><span                class="token punctuation">)</span><span class="token punctuation">;</span><br>axios<span class="token punctuation">.</span>interceptors<span class="token punctuation">.</span>request<span                    class="token punctuation">.</span><span class="token function">eject</span><span                    class="token punctuation">(</span>myInterceptor<span class="token punctuation">)</span><span                    class="token punctuation">;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><br>    </div><br>    <p>3、 给自定义的axios实例添加拦截器</p><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token keyword">var</span> instance <span                class="token operator">=</span> axios<span class="token punctuation">.</span><span                class="token function">create</span><span class="token punctuation">(</span><span                class="token punctuation">)</span><span class="token punctuation">;</span><br>instance<span class="token punctuation">.</span>interceptors<span class="token punctuation">.</span>request<span                    class="token punctuation">.</span><span class="token function">use</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span                    class="token punctuation">)</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><br>    </div><br>    <h2>八、错误处理</h2><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-jsx"><code class="  language-jsx">axios<span                class="token punctuation">.</span><span class="token function">get</span><span                class="token punctuation">(</span><span class="token string">'/user/12345'</span><span                class="token punctuation">)</span><br>  <span class="token punctuation">.</span><span class="token function">catch</span><span                    class="token punctuation">(</span><span class="token keyword">function</span><span                    class="token punctuation">(</span><span class="token parameter">error</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span><br>    <span class="token keyword">if</span><span class="token punctuation">(</span>error<span                    class="token punctuation">.</span>response<span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span><br>      <span class="token comment">//请求已经发出，但是服务器响应返回的状态吗不在2xx的范围内</span><br>      console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>error<span class="token punctuation">.</span>response<span                    class="token punctuation">.</span>data<span class="token punctuation">)</span><span                    class="token punctuation">;</span><br>      console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>error<span class="token punctuation">.</span>response<span                    class="token punctuation">.</span>status<span class="token punctuation">)</span><span                    class="token punctuation">;</span><br>      console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>error<span class="token punctuation">.</span>response<span                    class="token punctuation">.</span>header<span class="token punctuation">)</span><span                    class="token punctuation">;</span><br>    <span class="token punctuation">&#125;</span><span class="token keyword">else</span> <span                    class="token punctuation">&#123;</span><br>      <span class="token comment">//一些错误是在设置请求的时候触发</span><br>      console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span><span class="token string">'Error'</span><span                    class="token punctuation">,</span>error<span class="token punctuation">.</span>message<span                    class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token punctuation">&#125;</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span>error<span class="token punctuation">.</span>config<span                    class="token punctuation">)</span><span class="token punctuation">;</span><br>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span                    class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <h2>九、取消</h2><br>    <ul><br>        <li>你可以通过一个<code>cancel token</code>来取消一个请求</li><br>    </ul><br>    <ol><br>        <li>你可以通过<code>CancelToken.source</code>工厂函数来创建一个<code>cancel token</code><br>        </li><br>    </ol><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token keyword">var</span> CancelToken <span                class="token operator">=</span> axios<span class="token punctuation">.</span>CancelToken<span                class="token punctuation">;</span><br><span class="token keyword">var</span> source <span class="token operator">=</span> CancelToken<span                    class="token punctuation">.</span><span class="token function">source</span><span                    class="token punctuation">(</span><span class="token punctuation">)</span><span                    class="token punctuation">;</span></p><p>axios<span class="token punctuation">.</span><span class="token function">get</span><span                    class="token punctuation">(</span><span class="token string">‘/user/12345’</span><span                    class="token punctuation">,</span><span class="token punctuation">&#123;</span><br>  cancelToken<span class="token punctuation">:</span> source<span class="token punctuation">.</span>token<br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span                    class="token function">catch</span><span class="token punctuation">(</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">thrown</span><span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span><br>  <span class="token keyword">if</span><span class="token punctuation">(</span>axios<span                    class="token punctuation">.</span><span class="token function">isCancel</span><span                    class="token punctuation">(</span>thrown<span class="token punctuation">)</span><span                    class="token punctuation">)</span><span class="token punctuation">&#123;</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span                    class="token punctuation">(</span><span class="token string">‘Request canceled’</span><span                    class="token punctuation">,</span>thrown<span class="token punctuation">.</span>message<span                    class="token punctuation">)</span><span class="token punctuation">;</span><br>  <span class="token punctuation">&#125;</span><span class="token keyword">else</span> <span                    class="token punctuation">&#123;</span><br>    <span class="token comment">//handle error</span><br>  <span class="token punctuation">&#125;</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><p><span class="token comment">//取消请求（信息的参数可以设置的）</span><br>source<span class="token punctuation">.</span><span class="token function">cance</span><span                    class="token punctuation">(</span><span class="token string">“操作被用户取消”</span><span                    class="token punctuation">)</span><span class="token punctuation">;</span></p><p><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <ol start="2"><br>        <li>你可以给cancelToken构造函数传递一个executor function来创建一个cancel token:</li><br>    </ol><br>    <div class="_2Uzcx_"><br>        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy"><br>            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true"><br>                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path><br>            </svg><br>        </i></button><br>        <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token keyword">var</span> cancelToken <span                class="token operator">=</span> axios<span class="token punctuation">.</span>CancelToken<span                class="token punctuation">;</span><br><span class="token keyword">var</span> cance<span class="token punctuation">;</span><br>axios<span class="token punctuation">.</span><span class="token function">get</span><span                    class="token punctuation">(</span><span class="token string">'/user/12345'</span><span                    class="token punctuation">,</span><span class="token punctuation">&#123;</span><br>  cancelToken<span class="token punctuation">:</span> <span class="token keyword">new</span> <span                    class="token class-name">CancelToken</span><span class="token punctuation">(</span><span                    class="token keyword">function</span><span class="token punctuation">(</span><span                    class="token parameter">c</span><span class="token punctuation">)</span><span                    class="token punctuation">&#123;</span><br>    <span class="token comment">//这个executor函数接受一个cancel function作为参数</span><br>    cancel <span class="token operator">=</span> c<span class="token punctuation">;</span><br>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><br><span class="token comment">//取消请求</span><br><span class="token function">cancel</span><span class="token punctuation">(</span><span                    class="token punctuation">)</span><span class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div></p></article><div></div><div class="_1kCBjS">    <div class="_18vaTa">        <div class="_3BUZPB">            <div class="_2Bo4Th" role="button" tabindex="-1" aria-label="给文章点赞"><i aria-label="ic-like"                                                                                   class="anticon">                <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">                    <use xlink:href="#ic-like"></use>                </svg>            </i></div>            <span class="_1LOh_5" role="button" tabindex="-1" aria-label="查看点赞列表">267人点赞<i aria-label="icon: right"                                                                                           class="anticon anticon-right"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="right" width="1em" height="1em"                    fill="currentColor" aria-hidden="true"><path                    d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span>        </div>        <div class="_3BUZPB">            <div class="_2Bo4Th" role="button" tabindex="-1"><i aria-label="ic-dislike" class="anticon">                <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">                    <use xlink:href="#ic-dislike"></use>                </svg>            </i></div>        </div>    </div>    <div class="_18vaTa"><a class="_3BUZPB _1x1ok9 _1OhGeD" href="/nb/10418276" target="_blank"                            rel="noopener noreferrer"><i aria-label="ic-notebook" class="anticon">        <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">            <use xlink:href="#ic-notebook"></use>        </svg>    </i><span>通信</span></a>        <div class="_3BUZPB ant-dropdown-trigger">            <div class="_2Bo4Th"><i aria-label="ic-others" class="anticon">                <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">                    <use xlink:href="#ic-others"></use>                </svg>            </i></div>        </div>    </div></div><div class="_19DgIp" style="margin-top:24px;margin-bottom:24px"></div><div class="_13lIbp">    <div class="_191KSt">"小礼物走一走，来简书关注我"</div>    <button type="button" class="_1OyPqC _3Mi9q9 _2WY0RL _1YbC5u"><span>赞赏支持</span></button>    <span class="_3zdmIj">还没有人赞赏，支持一下</span></div><div class="d0hShY"><a class="_1OhGeD" href="/u/cc401bccfdf8" target="_blank" rel="noopener noreferrer"><img        class="_27NmgV"        src="https://upload.jianshu.io/users/upload_avatars/4499098/a839bb46-6e73-4404-b544-09f0dcd902e2?imageMogr2/auto-orient/strip|imageView2/1/w/100/h/100/format/webp"        alt="  "></a>    <div class="Uz-vZq">        <div class="Cqpr1X"><a class="HC3FFO _1OhGeD" href="/u/cc401bccfdf8" title="FunnySeeker" target="_blank"                               rel="noopener noreferrer">FunnySeeker</a><span class="_2WEj6j" title=""></span></div>        <div class="lJvI3S"><span>总资产3 (约0.35元)</span><span>共写了693字</span><span>获得273个赞</span><span>共175个粉丝</span>        </div>    </div>    <button data-locale="zh-CN" type="button" class="_1OyPqC _3Mi9q9"><span>关注</span></button></div>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
            <tag> axios </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue.js+Django 实现前后端分离</title>
      <link href="front/vue/old/vue-note1/"/>
      <url>front/vue/old/vue-note1/</url>
      
        <content type="html"><![CDATA[<h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><h3 id="环境的搭建"><a href="#环境的搭建" class="headerlink" title="环境的搭建"></a>环境的搭建</h3><ul><li><a href="https://www.jianshu.com/p/03a76b2e7e00">node.js</a></li><li><a href="https://www.jianshu.com/p/06a9f112867d">vue-cli</a></li><li><a href="https://victorfengming.gitee.io/blog/python-install-window/">python</a></li><li><a href="https://victorfengming.gitee.io/blog/django-note1/">django</a><h3 id="集成开发环境的搭建"><a href="#集成开发环境的搭建" class="headerlink" title="集成开发环境的搭建"></a>集成开发环境的搭建</h3></li><li>webstorm</li><li>pycharm</li><li>安装参考<a href="https://victorfengming.gitee.io/blog/pycharm-install/">这里</a>,激活破解以及设置,可以在我的<a href="https://github.com/victorfengming/jetbrains_settings">github</a>/<a href="https://gitee.com/victorfengming/jetbrains_settings">gitee</a>中clone下来    <h2 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h2></li></ul><h3 id="node-js安装"><a href="#node-js安装" class="headerlink" title="node.js安装"></a>node.js安装</h3><p><a href="https://nodejs.org/zh-cn/">官网</a>下载exe<br>傻瓜式下一步即可</p><h3 id="检查node版本"><a href="#检查node版本" class="headerlink" title="检查node版本"></a>检查node版本</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node --version</span><br></pre></td></tr></table></figure><h3 id="npm介绍"><a href="#npm介绍" class="headerlink" title="npm介绍"></a>npm介绍</h3><p>node的包管理工具,详情可以参考简书:<a href="https://www.jianshu.com/p/1ab15a647e83">NPM简介和安装</a></p><h3 id="检查npm版本"><a href="#检查npm版本" class="headerlink" title="检查npm版本"></a>检查npm版本</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm --version</span><br></pre></td></tr></table></figure><h2 id="入门"><a href="#入门" class="headerlink" title="入门"></a>入门</h2><h3 id="npm换源-淘宝源"><a href="#npm换源-淘宝源" class="headerlink" title="npm换源 - 淘宝源"></a>npm换源 - 淘宝源</h3><p>1.临时使用</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm --registry https:&#x2F;&#x2F;registry.npm.taobao.org install express</span><br></pre></td></tr></table></figure><p>2.持久使用</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">npm config set registry https:&#x2F;&#x2F;registry.npm.taobao.org</span><br><span class="line">&#x2F;&#x2F; 配置后可通过下面方式来验证是否成功</span><br><span class="line">npm config get registry</span><br><span class="line">&#x2F;&#x2F; 或npm info express</span><br></pre></td></tr></table></figure><h3 id="vue脚手架的安装"><a href="#vue脚手架的安装" class="headerlink" title="vue脚手架的安装"></a>vue脚手架的安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g @vue&#x2F;cli</span><br></pre></td></tr></table></figure><h3 id="安装-vue-cli-init"><a href="#安装-vue-cli-init" class="headerlink" title="安装 @vue/cli-init"></a>安装 @vue/cli-init</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm i -g @vue&#x2F;cli</span><br><span class="line">npm i -g @vue&#x2F;cli-init</span><br></pre></td></tr></table></figure><h2 id="进阶"><a href="#进阶" class="headerlink" title="进阶"></a>进阶</h2><h3 id="创建vue项目"><a href="#创建vue项目" class="headerlink" title="创建vue项目"></a>创建vue项目</h3><p>vue初始化基于webpack的my-project项目(项目名不能用大写字母)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vue init webpackage project_name</span><br></pre></td></tr></table></figure><h4 id="下面有一坨选项"><a href="#下面有一坨选项" class="headerlink" title="下面有一坨选项"></a>下面有一坨选项</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">? Project name my-project</span><br><span class="line">? Project description A Vue.js project</span><br><span class="line">? Author uplyw &lt;xxx@xxx.com&gt;</span><br><span class="line">? Vue build standalone</span><br><span class="line">? Install vue-router? Yes</span><br><span class="line">? Use ESLint to lint your code? No</span><br><span class="line">? Set up unit tests No</span><br><span class="line">? Setup e2e tests with Nightwatch? No</span><br><span class="line">? Should we run &#96;npm install&#96; for you after the project has been created? (recommended) npm</span><br></pre></td></tr></table></figure><p><a href="https://blog.csdn.net/AYKMe/article/details/84646571">vue init webpack my-project 选项详解</a></p><h3 id="先运行起来再说"><a href="#先运行起来再说" class="headerlink" title="先运行起来再说"></a>先运行起来再说</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run dev</span><br></pre></td></tr></table></figure><h3 id="加一个路由"><a href="#加一个路由" class="headerlink" title="加一个路由"></a>加一个路由</h3><p>在<code>router\index.js</code>中,加上一个</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  path: <span class="string">&#x27;/user&#x27;</span>,</span><br><span class="line">  name: <span class="string">&#x27;User&#x27;</span>,</span><br><span class="line">  component: User</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure><p>再去<code>vue_project\src\components</code>里面创建一个.vue文件,内容如下</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 这里直接就复制那个Hello的就OK了</span></span><br></pre></td></tr></table></figure><h2 id="高级"><a href="#高级" class="headerlink" title="高级"></a>高级</h2><h3 id="易用、简洁且高效的http库"><a href="#易用、简洁且高效的http库" class="headerlink" title="易用、简洁且高效的http库"></a>易用、简洁且高效的http库</h3><p>官网在这里:<a href="http://axios-js.com/">http://axios-js.com/</a></p><h3 id="安装axios-实现vue连接django"><a href="#安装axios-实现vue连接django" class="headerlink" title="安装axios,实现vue连接django"></a>安装axios,实现vue连接django</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install axios --save</span><br></pre></td></tr></table></figure><h3 id="vue-cli注册axios"><a href="#vue-cli注册axios" class="headerlink" title="vue-cli注册axios"></a>vue-cli注册axios</h3><p>首先在 main.js 中引入 axios</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br></pre></td></tr></table></figure><p>这时候如果在其它的组件中，是无法使用 axios 命令的。所以我们将 axios 改写为 Vue 的原型属性</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Vue.prototype.$http= axios</span><br></pre></td></tr></table></figure><p>在 main.js 中添加了这两行代码之后，就能直接在组件的 methods 中使用 $http命令</p><p>例如</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">methods: &#123;</span><br><span class="line"><span class="function"><span class="title">show</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">  <span class="built_in">this</span>.$http(&#123;</span><br><span class="line">    method: <span class="string">&#x27;get&#x27;</span>,</span><br><span class="line">    url: <span class="string">&#x27;/user&#x27;</span>,</span><br><span class="line">    data: &#123;</span><br><span class="line">      name: <span class="string">&#x27;virus&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line"> &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="配置-axios"><a href="#配置-axios" class="headerlink" title="配置 axios"></a>配置 axios</h3><p>实际上只有 url 是必须的<br>对于get请求</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">axios.get(<span class="string">&#x27;/user&#x27;</span>, &#123;</span><br><span class="line">      params:&#123;</span><br><span class="line">            name:<span class="string">&quot;virus&quot;</span>  </span><br><span class="line">      &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>更多详情参考:<a href="https://www.jianshu.com/p/e36956dc78b8">vue-cli 引入axios及跨域使用</a></p><h3 id="然后就访问会报错-别慌"><a href="#然后就访问会报错-别慌" class="headerlink" title="然后就访问会报错,别慌"></a>然后就访问会报错,别慌</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Access to XMLHttpRequest at &#39;http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;test&#x2F;&#39; from origin &#39;http:&#x2F;&#x2F;localhost:8080&#39; has been blocked by CORS policy: No &#39;Access-Control-Allow-Origin&#39; header is present on the requested resource.</span><br></pre></td></tr></table></figure><p>因为不允许跨站访问,也叫做跨域,这里我们就需要配置一下这个跨域了</p><p>这里参考:卖火柴的小女孩的<a href="https://segmentfault.com/a/1190000014396546">vue2.0 proxyTable配置，解决跨域</a></p><h2 id="难点"><a href="#难点" class="headerlink" title="难点"></a>难点</h2><p>上面的报错依旧没有解决,这并不是因为解决方案不正确,而是有其他的原因</p><h3 id="两天未解决的问题"><a href="#两天未解决的问题" class="headerlink" title="两天未解决的问题"></a>两天未解决的问题</h3><p>在使用vue和axios进行跨域请求的时候,一直以为是vue这边没有配置好,</p><p>尝试了很久,查了很多关于vue跨域的资料,还使用jq中的ajax直接进行访问都不好使</p><p>但是访问<a href="https://autumnfish.cn/api/joke">这个</a>好使,这就证明不是vue+axios和边的问题了,这里仅仅是指定一下url即可,在<code>config/index.js</code>中配置的仅仅的让<code>test.vue</code>文件中不用写上全部路径</p><p>原来是django里面没有设置允许跨域访问的原因,O(∩_∩)O哈哈~<br><a href="https://blog.csdn.net/apple9005/article/details/54427902">django解决跨域请求的问题</a></p><h3 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h3><p>具体实现如下:</p><h4 id="1-安装django-cors-headers"><a href="#1-安装django-cors-headers" class="headerlink" title="1.安装django-cors-headers"></a>1.安装django-cors-headers</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install django-cors-headers</span><br></pre></td></tr></table></figure><h4 id="2-在django的设置文件setting-py中-加入"><a href="#2-在django的设置文件setting-py中-加入" class="headerlink" title="2.在django的设置文件setting.py中,加入"></a>2.在django的设置文件<code>setting.py</code>中,加入</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">INSTALLED_APPS = [</span><br><span class="line">    ...</span><br><span class="line">    <span class="string">&#x27;corsheaders&#x27;</span>，</span><br><span class="line">    ...</span><br><span class="line"> ] </span><br><span class="line"></span><br><span class="line">MIDDLEWARE_CLASSES = (</span><br><span class="line">    ...</span><br><span class="line">    <span class="string">&#x27;corsheaders.middleware.CorsMiddleware&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;django.middleware.common.CommonMiddleware&#x27;</span>, <span class="comment"># 注意顺序</span></span><br><span class="line">    ...</span><br><span class="line">)</span><br><span class="line"><span class="comment">#跨域增加忽略</span></span><br><span class="line">CORS_ALLOW_CREDENTIALS = <span class="literal">True</span></span><br><span class="line">CORS_ORIGIN_ALLOW_ALL = <span class="literal">True</span></span><br><span class="line">CORS_ORIGIN_WHITELIST = (</span><br><span class="line">    <span class="string">&#x27;*&#x27;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">CORS_ALLOW_METHODS = (</span><br><span class="line">    <span class="string">&#x27;DELETE&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;GET&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;OPTIONS&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;PATCH&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;POST&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;PUT&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;VIEW&#x27;</span>,</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">CORS_ALLOW_HEADERS = (</span><br><span class="line">    <span class="string">&#x27;XMLHttpRequest&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;X_FILENAME&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;accept-encoding&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;authorization&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;content-type&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;dnt&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;origin&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;user-agent&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;x-csrftoken&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;x-requested-with&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;Pragma&#x27;</span>,</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>之后报错,别慌!</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:</span><br><span class="line"></span><br><span class="line">ERRORS:</span><br><span class="line">?: (corsheaders.E013) Origin &#39;*&#39; in CORS_ORIGIN_WHITELIST is missing  scheme or netloc</span><br><span class="line">        HINT: Add a scheme (e.g. https:&#x2F;&#x2F;) or netloc (e.g. example.com).</span><br></pre></td></tr></table></figure><p>然后在配合的<a href="https://www.cnblogs.com/sea-stream/p/10965147.html">这个</a>全部解决了问题,完美简直</p><h2 id="项目的源码地址"><a href="#项目的源码地址" class="headerlink" title="项目的源码地址"></a>项目的源码地址</h2><p>gitee:<a href="https://gitee.com/victorfengming/vue_django_project">vue_django_project</a><br>大家可以clone下来进行参考,如果觉得有用的可以给小编<code>star</code>一下,你的支持就是我的动力!</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
            <tag> django </tag>
            
            <tag> axios </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据分析之pandas笔记</title>
      <link href="python/data_analysis/pandas/"/>
      <url>python/data_analysis/pandas/</url>
      
        <content type="html"><![CDATA[<h3 id="Pandas"><a href="#Pandas" class="headerlink" title="Pandas"></a>Pandas</h3><p>一个用于表示表格类型的内容</p><ul><li>课时4：jupyter21 分22 秒</li><li>课时5：pandas的内容24 分31 秒</li><li>课时6：series内容38 分19 秒</li><li>课时7：dataframe25 分50 秒</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 载入pandas库</span></span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">s = pd.Series([<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>])</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">s</span><br></pre></td></tr></table></figure><pre><code>0     21     42     63     84    10dtype: int64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">d = pd.DataFrame([</span><br><span class="line"> [<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>],</span><br><span class="line"> [<span class="number">7</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">7</span>,<span class="number">15</span>],</span><br><span class="line">])</span><br><span class="line"></span><br><span class="line">d</span><br></pre></td></tr></table></figure><div><style scoped>    .dataframe tbody tr th:only-of-type {        vertical-align: middle;    }<pre><code>.dataframe tbody tr th &#123;    vertical-align: top;&#125;.dataframe thead th &#123;    text-align: right;&#125;</code></pre><p></style></p><table border="1" class="dataframe">  <thead>    <tr style="text-align: right;">      <th></th>      <th>0</th>      <th>1</th>      <th>2</th>      <th>3</th>      <th>4</th>    </tr>  </thead>  <tbody>    <tr>      <th>0</th>      <td>2</td>      <td>4</td>      <td>6</td>      <td>8</td>      <td>10</td>    </tr>    <tr>      <th>1</th>      <td>7</td>      <td>3</td>      <td>4</td>      <td>7</td>      <td>15</td>    </tr>  </tbody></table></div><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">d[<span class="number">0</span>]</span><br></pre></td></tr></table></figure><pre><code>0    21    7Name: 0, dtype: int64</code></pre><p>这里要注意直接用中括号获取的是,列,因为比如我们要获取一个表中的age属性,通常的拿这age一列的数据出来,所以想要获取一条数据,需要再中括号一下</p><p>获取一行怎么获取</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">d.loc[<span class="number">0</span>]</span><br></pre></td></tr></table></figure><pre><code>0     21     42     63     84    10Name: 0, dtype: int64</code></pre><p>这个给我们返回的是一个series<br>实际上这个dataframe是由多个series组成的<br>所以我们可以这么写</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">d2 = pd.DataFrame([</span><br><span class="line"> pd.Series([<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>]),</span><br><span class="line"> pd.Series([<span class="number">7</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">7</span>,<span class="number">15</span>]),</span><br><span class="line">])</span><br><span class="line">d2</span><br></pre></td></tr></table></figure><div><style scoped>    .dataframe tbody tr th:only-of-type {        vertical-align: middle;    }<pre><code>.dataframe tbody tr th &#123;    vertical-align: top;&#125;.dataframe thead th &#123;    text-align: right;&#125;</code></pre><p></style></p><table border="1" class="dataframe">  <thead>    <tr style="text-align: right;">      <th></th>      <th>0</th>      <th>1</th>      <th>2</th>      <th>3</th>      <th>4</th>    </tr>  </thead>  <tbody>    <tr>      <th>0</th>      <td>2</td>      <td>4</td>      <td>6</td>      <td>8</td>      <td>10</td>    </tr>    <tr>      <th>1</th>      <td>7</td>      <td>3</td>      <td>4</td>      <td>7</td>      <td>15</td>    </tr>  </tbody></table></div><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">class1 = pd.Series(&#123;<span class="string">&#x27;hong&#x27;</span>: <span class="number">50</span>, <span class="string">&#x27;huang&#x27;</span>: <span class="number">90</span>, <span class="string">&#x27;qing&#x27;</span>: <span class="number">60</span>&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改字典索引</span></span><br><span class="line">class1_values = &#123;<span class="string">&#x27;hong&#x27;</span>: <span class="number">50</span>, <span class="string">&#x27;huang&#x27;</span>: <span class="number">90</span>, <span class="string">&#x27;qing&#x27;</span>: <span class="number">60</span>&#125;</span><br><span class="line">class1_index = [<span class="string">&#x27;hong&#x27;</span>, <span class="string">&#x27;lv&#x27;</span>, <span class="string">&#x27;lan&#x27;</span>]</span><br><span class="line"><span class="comment"># 这个地方的键是根据index参数设置的,然后前面的那个字典的键就不要了</span></span><br><span class="line">class1 = pd.Series(class1_values, index=class1_index)</span><br><span class="line">class1</span><br></pre></td></tr></table></figure><pre><code>hong    50.0lv       NaNlan      NaNdtype: float64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">class1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 值数据，输出类型为array，还是ndarray数组</span></span><br><span class="line">class1.values</span><br><span class="line"></span><br><span class="line"><span class="comment"># 索引，输出index类型（Pandas独有的索引类型）,本质上就是ndarray</span></span><br><span class="line">class1.index</span><br><span class="line"></span><br><span class="line">class1.index[<span class="number">2</span>]</span><br><span class="line">class1.index.values</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>array([&#39;hong&#39;, &#39;lv&#39;, &#39;lan&#39;], dtype=object)</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">class1_index</span><br><span class="line">class1.hong</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>50.0</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">class1[[<span class="number">1</span>,<span class="number">2</span>,<span class="number">0</span>]]</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>lv       NaNlan      NaNhong    50.0dtype: float64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">class1[<span class="number">0</span>:<span class="number">1</span>]</span><br></pre></td></tr></table></figure><pre><code>hong    50.0dtype: float64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 直接就能记性判断</span></span><br><span class="line">class1 &gt; <span class="number">6</span></span><br><span class="line"><span class="comment"># 这个Nan值你怎么判断都是False</span></span><br></pre></td></tr></table></figure><pre><code>hong     Truelv      Falselan     Falsedtype: bool</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 还能这样写</span></span><br><span class="line"><span class="comment"># 这种写法很类似于数据库的写法</span></span><br><span class="line">class1[class1&gt;<span class="number">6</span>]</span><br></pre></td></tr></table></figure><pre><code>hong    50.0dtype: float64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 直接就全都加一</span></span><br><span class="line">class1+<span class="number">1</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>hong    51.0lv       NaNlan      NaNdtype: float64</code></pre><ul><li>这种整体的加一,他是效率非常非常高的</li><li>如果是我们的列表,想要实现这个效果,那就得循环这个列表<br>从列表中获取一个数据,把这个数据+1,放到新的列表中</li><li>而我们这个是将三条数据同时拿出来(就像并发一样),然后同时进行+1操作<br>然后在同时放到一个新的里面.</li><li>我们可以通过那个运算时间的魔术命令来帮忙验证一下</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">%%timeit</span><br><span class="line"><span class="comment"># 修改字典索引</span></span><br><span class="line">class2_values = [<span class="number">1024</span>,<span class="number">3</span>,<span class="number">5</span>,<span class="number">7</span>,<span class="number">9</span>,<span class="number">10</span>,<span class="number">13</span>,<span class="number">115</span>,<span class="number">127</span>,<span class="number">149</span>,<span class="number">221</span>]</span><br><span class="line"><span class="comment"># 这个地方的键是根据index参数设置的,然后前面的那个字典的键就不要了</span></span><br><span class="line">class2 = pd.Series(class2_values)</span><br><span class="line">class2+<span class="number">1</span></span><br></pre></td></tr></table></figure><pre><code>198 µs ± 9.37 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">%%timeit</span><br><span class="line">class2+<span class="number">1</span></span><br></pre></td></tr></table></figure><pre><code>100 µs ± 3.56 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">%%timeit</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">100000</span>):</span><br><span class="line">    i+=<span class="number">1</span></span><br></pre></td></tr></table></figure><pre><code>4.12 ms ± 108 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">%%timeit</span><br><span class="line">a = pd.Series(<span class="built_in">range</span>(<span class="number">100000</span>))</span><br><span class="line">a+<span class="number">1</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>562 µs ± 72 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)</code></pre><p>我猜可能是因为这个数据量不够大,还显示不出来这个库的优势,所以得多试试才行<br>有的时候需要用GPU来计算,如果用CPU,会非常耗CPU,因为GPU更擅长这种小量的计算,他就相当于一堆小学生,这中加减乘除,小学生比CPU数学家更厉害</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 不仅能够进行加,减号,还能乘除,取余,底板除</span></span><br><span class="line">print(class2 // <span class="number">2</span>) </span><br></pre></td></tr></table></figure><pre><code>11.011.0</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">class2 = pd.Series([<span class="number">1024</span>,<span class="number">3</span>,<span class="number">5</span>,<span class="number">7</span>,<span class="number">9</span>,<span class="number">10</span>,<span class="number">13</span>,<span class="number">115</span>,<span class="number">127</span>,<span class="number">149</span>,<span class="number">221</span>])</span><br><span class="line"><span class="comment"># 平均数</span></span><br><span class="line">print(class2.mean())</span><br><span class="line">print(np.mean(class2))</span><br><span class="line">class2</span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>153.0153.00     10241        32        53        74        95       106       137      1158      1279      14910     221dtype: int64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">class3 = pd.Series([<span class="number">1024</span>,<span class="number">13</span>,<span class="number">5</span>,<span class="number">7</span>,<span class="number">9</span>,<span class="number">10</span>,<span class="number">1</span>,<span class="number">115</span>,<span class="number">127</span>,<span class="number">149</span>,<span class="number">221</span>])</span><br><span class="line"><span class="comment"># 中位数</span></span><br><span class="line"><span class="comment"># 通过库中的函数调用</span></span><br><span class="line">print(np.median(class3))</span><br><span class="line"><span class="comment"># 自身属性调用写法</span></span><br><span class="line">print(class3.median())</span><br><span class="line"><span class="comment"># 中位数如果有两个数据,那就是这两个数据的平均数</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>13.013.0</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 方差</span></span><br><span class="line">class2.var()</span><br></pre></td></tr></table></figure><pre><code>89190.6</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 标准差</span></span><br><span class="line">class2.std()</span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>298.6479532827908</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">print(class2)</span><br><span class="line">print(<span class="string">&quot;-&quot;</span>*<span class="number">50</span>)</span><br><span class="line">print(class2+<span class="number">1</span>)</span><br><span class="line">print(<span class="string">&quot;-&quot;</span>*<span class="number">50</span>)</span><br><span class="line"><span class="comment"># 全判断在不在容器中</span></span><br><span class="line"><span class="comment"># 这个容器包括类似于字典的键和值,都都算上,只有有都行,都算存在啊</span></span><br><span class="line">print(<span class="number">10</span> <span class="keyword">in</span> class2)</span><br><span class="line">print(<span class="string">&quot;-&quot;</span>*<span class="number">50</span>)</span><br><span class="line">print(<span class="number">5</span> <span class="keyword">in</span> class2 + <span class="number">1</span>)</span><br><span class="line"><span class="comment"># 浮点数运算不准的问题</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>0     10241        32        53        74        95       106       137      1158      1279      14910     221dtype: int64--------------------------------------------------0     10251        42        63        84       105       116       147      1168      1289      15010     222dtype: int64--------------------------------------------------True--------------------------------------------------True</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 然后问我们可以取出来values</span></span><br><span class="line">print(<span class="number">4</span> <span class="keyword">in</span> class2) </span><br><span class="line">print(<span class="number">4</span> <span class="keyword">in</span> class2.values)</span><br></pre></td></tr></table></figure><pre><code>TrueFalse</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># values值修改</span></span><br><span class="line">class2[<span class="string">&#x27;ming&#x27;</span>] = <span class="number">0</span></span><br><span class="line">class2[<span class="string">&#x27;hua&#x27;</span>] = <span class="number">0</span></span><br><span class="line">class2[<span class="string">&#x27;hong&#x27;</span>] = <span class="number">0</span></span><br><span class="line"></span><br><span class="line">class2[[<span class="string">&#x27;hua&#x27;</span>,<span class="string">&#x27;hong&#x27;</span>]] = <span class="number">55</span></span><br><span class="line">class2[[<span class="string">&#x27;hua&#x27;</span>,<span class="string">&#x27;hong&#x27;</span>]] = [<span class="number">35</span>, <span class="number">55</span>]</span><br><span class="line">class2[<span class="string">&#x27;hua&#x27;</span>,<span class="string">&#x27;hong&#x27;</span>] = [<span class="number">1</span>, <span class="number">2</span>]  <span class="comment"># 一层也可以</span></span><br><span class="line">class2</span><br><span class="line"></span><br></pre></td></tr></table></figure><pre><code>0       10241          32          53          74          95         106         137        1158        1279        14910       221ming       0hua        1hong       2dtype: int64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 深拷贝</span></span><br><span class="line">class4 = class2.copy()</span><br><span class="line">class4 = class4+<span class="number">1</span></span><br><span class="line">print(class2)</span><br><span class="line">class4</span><br></pre></td></tr></table></figure><pre><code>0       10241          32          53          74          95         106         137        1158        1279        14910       221ming       0hua        1hong       2dtype: int640       10251          42          63          84         105         116         147        1168        1289        15010       222ming       1hua        2hong       3dtype: int64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 索引也可以单独的进行修改</span></span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">class2.index = [<span class="number">22</span>,<span class="number">23</span>,<span class="number">24</span>,<span class="number">28</span>,<span class="number">24</span>,<span class="number">29</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">8</span>,<span class="number">5</span>,<span class="number">9</span>,<span class="number">21</span>]</span><br><span class="line">class2</span><br></pre></td></tr></table></figure><pre><code>22    102423       324       528       724       929      101       132      1153      1274      1498      2215        09        121       2dtype: int64</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 这个csv路径不能有中文,否则获取失败</span></span><br><span class="line">df = pd.read_csv(<span class="string">&quot;./source/test.csv&quot;</span>)</span><br><span class="line">df</span><br><span class="line"></span><br></pre></td></tr></table></figure><div><style scoped>    .dataframe tbody tr th:only-of-type {        vertical-align: middle;    }<pre><code>.dataframe tbody tr th &#123;    vertical-align: top;&#125;.dataframe thead th &#123;    text-align: right;&#125;</code></pre><p></style></p><table border="1" class="dataframe">  <thead>    <tr style="text-align: right;">      <th></th>      <th>ro</th>      <th>c1</th>      <th>c2</th>      <th>c3</th>      <th>c4</th>      <th>c5</th>      <th>c6</th>      <th>c7</th>      <th>c8</th>      <th>c9</th>      <th>c10</th>      <th>c11</th>      <th>c12</th>      <th>c13</th>      <th>c14</th>      <th>c15</th>      <th>c16</th>      <th>c17</th>      <th>c18</th>    </tr>  </thead>  <tbody>    <tr>      <th>0</th>      <td>a</td>      <td>0</td>      <td>5</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>      <td>10</td>    </tr>    <tr>      <th>1</th>      <td>b</td>      <td>1</td>      <td>6</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>      <td>11</td>    </tr>    <tr>      <th>2</th>      <td>c</td>      <td>2</td>      <td>7</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>      <td>12</td>    </tr>    <tr>      <th>3</th>      <td>d</td>      <td>3</td>      <td>8</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>      <td>13</td>    </tr>    <tr>      <th>4</th>      <td>e</td>      <td>4</td>      <td>9</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>      <td>14</td>    </tr>  </tbody></table></div><p>csv中的数据都是用逗号隔开的,出自:<br><a href="https://www.jianshu.com/p/9c12fb248ccc">python:pandas——read_csv方法</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> data_analysis </tag>
            
            <tag> pandas </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据分析基础-概述</title>
      <link href="python/data_analysis/pre/"/>
      <url>python/data_analysis/pre/</url>
      
        <content type="html"><![CDATA[<ul><li>数据分析<ul><li>装X部分<a href="http://pypl.github.io/PYPL.html">PYPI编程语言流行榜</a><br>TIOBE编程语言排行榜 TOP榜单</li><li><a href="https://www.jianshu.com/p/103f49580baa">处理数据分析的库</a><ul><li>Pandas</li><li>Matplotlib</li><li>NumPy</li><li>参考:<a href="https://www.cnblogs.com/chaojiyingxiong/p/9939303.html">python数据分析中常用的库</a></li></ul></li><li>数据的表现形式</li></ul></li><li>新环境 -&gt; anaconda<ul><li>anaconda和python之间的<a href="http://ynvictor.xyz/index/Python_data/md/rumen-anaconda.html">关系</a><ul><li>翻译:<a href="https://cn.bing.com/search?q=%E7%BF%BB%E8%AF%91&PC=U316&FORM=CHROMN">bing</a></li><li>比喻:ubuntu和linux</li></ul></li><li>pycharm与anaconda之间的关系<ul><li>解释器</li><li>集成环境</li></ul></li></ul></li></ul><ul><li><p>python run</p><ul><li>交互式</li><li>解释执行</li><li><code>start /b</code></li></ul></li><li><p>交互式编译器    </p><ul><li><a href="http://source.yufengming.com/data_science/md/rumen-jupyter.html">jupyter</a><ul><li>介绍:<a href="https://www.jianshu.com/p/91365f343585">Jupyter Notebook介绍、安装及使用教程</a>    </li><li>cell概念</li><li>混合编程:md嵌入<ul><li>导出格式<ul><li>html</li><li>py</li><li>md</li><li>ipynb</li></ul></li><li><a href="https://www.jianshu.com/p/e45deef2f317">IPython魔术命令</a><ul><li>time计算<ul><li><a href="https://www.jianshu.com/p/48b7c31c5a88">ipython的使用与安装</a></li></ul></li></ul></li></ul></li><li>分段执行<ul><li>原因: <ul><li>内存需要</li><li>性能因素</li></ul></li><li>差点就NB坏了-&gt;jetbrains</li></ul></li></ul></li></ul></li><li><p>markdown: 三行代码实现markdown转换成html(模板的本质)  </p><ul><li><a href="https://blog.csdn.net/jhgjdfhre/article/details/52253630">参考的这里</a>  </li><li><a href="https://www.smslit.top/2018/10/16/md2html_python/">正式点的</a></li></ul></li><li><p>包管理工具:</p></li><li><p>环境控制</p></li><li><p>虚拟环境</p></li><li><p>容器</p></li><li><p>性能问题-&gt;</p><ul><li>在线编辑器</li></ul></li><li><p>文档工具:gitbook</p><ul><li><a href="https://www.gitbook.com/">https://www.gitbook.com/</a>    </li><li><a href="https://www.jianshu.com/p/421cc442f06c">https://www.jianshu.com/p/421cc442f06c</a></li></ul></li><li><p>本地思维导图</p><ul><li>xmind<ul><li>简介 : 本地缩进层级导入  </li><li>安装以及破解 : <a href="http://www.manongjc.com/article/39182.html">http://www.manongjc.com/article/39182.html</a></li></ul></li></ul></li></ul><p>Pandas数据存取</p><ul><li><p>文本类数据(演示)</p><ul><li>csv<a href="https://www.jianshu.com/p/7d15ff418310">文件格式</a></li><li>JSON</li></ul></li><li><p>数据分析的结果</p><ul><li>表示形式<ul><li><a href="file:///D:/JupyterProjects/Python_data/md/matplotlib-tuBiao.html">常见图表</a><ul><li>折线图</li><li>散点图／气泡图</li><li>条形图／柱状图</li><li>饼图</li><li>直方图</li><li>箱线图</li><li>热力图    </li></ul></li><li>Python可视化<ul><li>绘图库<br>  -Matplotlib<ul><li>演示</li></ul></li></ul></li></ul></li></ul></li></ul><p>附加:gitee+github配置多个git远程仓库                </p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> data_analysis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tornado学习笔记day07</title>
      <link href="python/tornado/tornado-note7/"/>
      <url>python/tornado/tornado-note7/</url>
      
        <content type="html"><![CDATA[<h3 id="同步"><a href="#同步" class="headerlink" title="同步"></a>同步</h3><h4 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h4><p>同步就是按部就班的依次执行我们的代码  </p><h4 id="进阶"><a href="#进阶" class="headerlink" title="进阶"></a>进阶</h4><p>但是有些情况我们有一些比较耗时的从操作,比如去别的地方拿点资源,去其他网站请求数据,去访问数据库,上传文件等等,所以这里面优点瑕疵,有小编一一道来<br>比如这样</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27; 本模块的功能:&lt;同步异步demo&gt;&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这个就相等于一个客户端的请求</span></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加一个耗时的操作</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">longIO</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始耗时操作&quot;</span>)</span><br><span class="line">    time.sleep(<span class="number">5</span>)</span><br><span class="line">    print(<span class="string">&quot;结束耗时操作&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqA</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqA&quot;</span>)</span><br><span class="line">    longIO()</span><br><span class="line">    print(<span class="string">&quot;结束处理reqA&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这个就相等于另一个客户端的请求</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqB</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqB&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;结束处理reqB&quot;</span>)</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>():</span></span><br><span class="line">    <span class="comment"># 这就是同步在处理</span></span><br><span class="line">    reqA()</span><br><span class="line">    reqB()</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        # 如果你要想写死循环,你不要直接写死循环,你得睡一睡</span></span><br><span class="line"><span class="string">        # 为什么要睡一睡呢,因为你要是不睡你会发现你的CPU利用率占100%</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        time.sleep(<span class="number">0.1</span>)</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure><p>结果</p><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">开始处理reqA</span><br><span class="line">开始耗时操作# 这里等待了5秒钟</span><br><span class="line">结束耗时操作</span><br><span class="line">结束处理reqA</span><br><span class="line">开始处理reqB</span><br><span class="line">结束处理reqB</span><br></pre></td></tr></table></figure><p>在请求中添加了一个耗时的操作,导致了我们的同步的效率特别低了,这样也体现不出我们tornado高效的优点</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                 神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="异步"><a href="#异步" class="headerlink" title="异步"></a>异步</h3><p>你干一件事情的同事又去干另一件事情</p><h4 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h4><p>对于耗时的操作,会交给别人(另一个线程)处理,我们继续向下执行,当别人结束耗时操作后,再将处理结果返回给我们</p><h4 id="回调函数实现异步"><a href="#回调函数实现异步" class="headerlink" title="回调函数实现异步"></a>回调函数实现异步</h4><p>异步其实我们已经用了,js里面有一个很明显的异步,就是在我们发ajax的时候,当我们发完ajax就去干别的活去了,后来ajax有响应了我们才搭理他</p><p>来来来,代码演示如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;异步演示demo&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这个就相等于一个客户端的请求</span></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> threading</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27; 添加一个耗时的操作&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">这样就会有一个问题,这个run()函数的返回值我们接受不到</span></span><br><span class="line"><span class="string">为了解决这个问题,我们需要写一个函数,这个函数叫做回调函数</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">longIO</span>(<span class="params">callback</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span>(<span class="params">cb</span>):</span></span><br><span class="line">        print(<span class="string">&quot;开始耗时操作&quot;</span>)</span><br><span class="line">        time.sleep(<span class="number">3</span>)</span><br><span class="line">        print(<span class="string">&quot;结束耗时操作&quot;</span>)</span><br><span class="line">        cb(<span class="string">&quot;victor is a wonderful man&quot;</span>)</span><br><span class="line">    threading.Thread(</span><br><span class="line">        target=run,</span><br><span class="line">        args=(callback,)</span><br><span class="line">    ).start()</span><br></pre></td></tr></table></figure><p>这个longio这部分 ,就像ajax一样都不用我们来写了</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">finish</span>(<span class="params">data</span>):</span></span><br><span class="line">    print(<span class="string">&quot;开始处理回调函数&quot;</span>)</span><br><span class="line">    print(<span class="string">&quot;接受到longIO的数据为：&quot;</span>,data)</span><br><span class="line">    print(<span class="string">&quot;结束处理回调函数&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqA</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqA&quot;</span>)</span><br><span class="line">    longIO(finish)</span><br><span class="line">    print(<span class="string">&quot;结束处理reqA&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这个就相等于另一个客户端的请求</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqB</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqB&quot;</span>)</span><br><span class="line">    time.sleep(<span class="number">1</span>)</span><br><span class="line">    print(<span class="string">&quot;结束处理reqB&quot;</span>)</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>():</span></span><br><span class="line">    <span class="comment"># 这就是同步在处理</span></span><br><span class="line">    reqA()</span><br><span class="line">    reqB()</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        # 如果你要想写死循环,你不要直接写死循环,你得睡一睡</span></span><br><span class="line"><span class="string">        # 为什么要睡一睡呢,因为你要是不睡你会发现你的CPU利用率占100%</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        time.sleep(<span class="number">0.1</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure><p>异步只是说tornado能处理多个请求了,你浏览器该等还是得等着</p><h4 id="协程实现异步"><a href="#协程实现异步" class="headerlink" title="协程实现异步"></a>协程实现异步</h4><p>协程还不理解呢,还想实现异步,你就实现就行了</p><p>不用管拥护啥了,进程线程你们搞起来都麻烦呢,更别说协程了</p><h5 id="版本1"><a href="#版本1" class="headerlink" title="版本1"></a>版本1</h5><p>最low的一个初级版本</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这个就相等于一个客户端的请求</span></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"></span><br><span class="line">gen = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加一个耗时的操作</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">longIO</span>():</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span>():</span></span><br><span class="line">        print(<span class="string">&quot;开始耗时操作&quot;</span>)</span><br><span class="line">        time.sleep(<span class="number">3</span>)</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            <span class="keyword">global</span> gen</span><br><span class="line">            gen.send(<span class="string">&quot;victor is wonderful!!!&quot;</span>)</span><br><span class="line">        <span class="keyword">except</span> StopIteration <span class="keyword">as</span> e:</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">        print(<span class="string">&quot;结束耗时操作&quot;</span>)</span><br><span class="line">    threading.Thread(</span><br><span class="line">        target=run,</span><br><span class="line">    ).start()</span><br><span class="line"><span class="comment"># 这个longio这部分 ,就像ajax一样都不用我们来写了</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">这样就会有一个问题,这个run()函数的返回值我们接受不到</span></span><br><span class="line"><span class="string">为了解决这个问题,我们需要写一个函数,这个函数叫做回调函数</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqA</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqA&quot;</span>)</span><br><span class="line">    res = <span class="keyword">yield</span> longIO()</span><br><span class="line">    print(<span class="string">&quot;接受到longIO的数据为：&quot;</span>,res)</span><br><span class="line">    <span class="comment"># 这里就相当于挂起了</span></span><br><span class="line">    print(<span class="string">&quot;结束处理reqA&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这个就相等于另一个客户端的请求</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqB</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqB&quot;</span>)</span><br><span class="line">    time.sleep(<span class="number">1</span>)</span><br><span class="line">    print(<span class="string">&quot;结束处理reqB&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>():</span></span><br><span class="line">    <span class="comment"># 这就是同步在处理</span></span><br><span class="line">    <span class="keyword">global</span> gen</span><br><span class="line">    gen = reqA()    <span class="comment"># 生成一个生成器</span></span><br><span class="line">    <span class="built_in">next</span>(gen)   <span class="comment"># 执行reqA</span></span><br><span class="line"></span><br><span class="line">    reqB()</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        # 如果你要想写死循环,你不要直接写死循环,你得睡一睡</span></span><br><span class="line"><span class="string">        # 为什么要睡一睡呢,因为你要是不睡你会发现你的CPU利用率占100%</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        time.sleep(<span class="number">0.1</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure><h5 id="版本2"><a href="#版本2" class="headerlink" title="版本2"></a>版本2</h5><h6 id="我们有一个问题"><a href="#我们有一个问题" class="headerlink" title="我们有一个问题"></a>我们有一个问题</h6><p>版本1中在调用reqA的时候和reqB的调用方式可不一样的啊<br>也就数不能将其视为简单的函数,而是需要作为生成器来用,我们想的时候是当成一个普通函数来对待</p><h6 id="现实"><a href="#现实" class="headerlink" title="现实"></a>现实</h6><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">global</span> gen</span><br><span class="line">gen = reqA()    <span class="comment"># 生成一个生成器</span></span><br><span class="line"><span class="built_in">next</span>(gen)   <span class="comment"># 执行reqA</span></span><br></pre></td></tr></table></figure><h6 id="理想"><a href="#理想" class="headerlink" title="理想"></a>理想</h6><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reqA()   <span class="comment"># 仅仅的简单的调用</span></span><br></pre></td></tr></table></figure><p>这个时候寄需要我们的<code>装饰器</code>来登场了</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27; 装饰器还会写么&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">genCoroutine</span>(<span class="params">func</span>):</span></span><br><span class="line">    <span class="comment"># 这个是带有参数的装饰器</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">wapper</span>(<span class="params">*args,**kwargs</span>):</span></span><br><span class="line">        <span class="comment"># 其实说白了还是那三句话</span></span><br><span class="line">        <span class="keyword">global</span> gen</span><br><span class="line">        gen = func(*args,**kwargs)  <span class="comment"># 生成一个生成器</span></span><br><span class="line">        <span class="built_in">next</span>(gen)  <span class="comment"># 执行reqA</span></span><br><span class="line">    <span class="keyword">return</span> wapper </span><br></pre></td></tr></table></figure><p>然后定义的时候</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@genCoroutine</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqA</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqA&quot;</span>)</span><br><span class="line">    res = <span class="keyword">yield</span> longIO()</span><br><span class="line">    print(<span class="string">&quot;接受到longIO的数据为：&quot;</span>,res)</span><br><span class="line">    <span class="comment"># 这里就相当于挂起了</span></span><br><span class="line">    print(<span class="string">&quot;结束处理reqA&quot;</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>然后执行的时候</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;这个就相等于另一个客户端的请求 &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqB</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqB&quot;</span>)</span><br><span class="line">    time.sleep(<span class="number">1</span>)</span><br><span class="line">    print(<span class="string">&quot;结束处理reqB&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>():</span></span><br><span class="line">    <span class="comment"># 这就是同步在处理</span></span><br><span class="line">    <span class="comment"># global gen</span></span><br><span class="line">    <span class="comment"># gen = reqA()    # 生成一个生成器</span></span><br><span class="line">    <span class="comment"># next(gen)   # 执行reqA</span></span><br><span class="line">    reqA()</span><br><span class="line">    reqB()</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        # 如果你要想写死循环,你不要直接写死循环,你得睡一睡</span></span><br><span class="line"><span class="string">        # 为什么要睡一睡呢,因为你要是不睡你会发现你的CPU利用率占100%</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        time.sleep(<span class="number">0.1</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure><h5 id="版本3"><a href="#版本3" class="headerlink" title="版本3"></a>版本3</h5><p>其实版本2中还有一个问题,他存在一个全局的gen变量,说白了就是假装让他不再那块儿 </p><p>这个是最复杂版本,看看吧</p><ol><li>文档说明,导入相关模块</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"></span><br></pre></td></tr></table></figure><ol start="2"><li>定义装饰器(最重要的部分,实现异步,高效,并发的原理)</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">genCoroutine</span>(<span class="params">func</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    这个好多人就屡不清了</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">wapper</span>(<span class="params">*args, **kwargs</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        这样的话这个装饰器就麻烦了,因为我还得要这个全局的gen啊</span></span><br><span class="line"><span class="string">        我需要获得多个生成器</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        gen1 = func()  <span class="comment"># reqA的生成器</span></span><br><span class="line">        gen2 = <span class="built_in">next</span>(gen1)  <span class="comment"># longIO的生成器</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 在这里面创建我的线程</span></span><br><span class="line">        <span class="comment"># 挂起他</span></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">run</span>(<span class="params">g</span>):</span></span><br><span class="line">            <span class="comment"># 这个就是执行longIO去了</span></span><br><span class="line">            res = <span class="built_in">next</span>(g)</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                gen1.send(res)  <span class="comment"># 返回给reqA数据</span></span><br><span class="line">            <span class="keyword">except</span> StopIteration <span class="keyword">as</span> e:</span><br><span class="line">                <span class="comment"># 啥都不干</span></span><br><span class="line">                <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">        threading.Thread(</span><br><span class="line">            target=run, args=(gen2,)</span><br><span class="line">        ).start()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> wapper</span><br></pre></td></tr></table></figure><ol start="3"><li>最难执行的部分</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"># 添加一个耗时的操作</span></span><br><span class="line"><span class="string"># handler获取数据,(数据库,其他服务器,循环耗时)</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">longIO</span>():</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    现在你只需要知道你的耗时的操作是啥,</span></span><br><span class="line"><span class="string">    线程的东西你不用管了</span></span><br><span class="line"><span class="string">    tornado都帮你弄好了</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    print(<span class="string">&quot;开始耗时操作&quot;</span>)</span><br><span class="line">    time.sleep(<span class="number">3</span>)</span><br><span class="line">    print(<span class="string">&quot;结束耗时操作&quot;</span>)</span><br><span class="line">    <span class="comment"># 结束耗时操作后的返回数据</span></span><br><span class="line">    <span class="keyword">yield</span> <span class="string">&quot;victor is a cool man&quot;</span></span><br></pre></td></tr></table></figure><ol start="4"><li>被装饰函数定义</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@genCoroutine</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqA</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqA&quot;</span>)</span><br><span class="line">    res = <span class="keyword">yield</span> longIO()</span><br><span class="line">    print(<span class="string">&quot;接受到longIO的数据为：&quot;</span>, res)</span><br><span class="line">    <span class="comment"># 这里就相当于挂起了</span></span><br><span class="line">    print(<span class="string">&quot;结束处理reqA&quot;</span>)</span><br></pre></td></tr></table></figure><ol start="5"><li>另一个耗时函数</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27; 这个就相等于另一个客户端的请求&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reqB</span>():</span></span><br><span class="line">    print(<span class="string">&quot;开始处理reqB&quot;</span>)</span><br><span class="line">    time.sleep(<span class="number">1</span>)</span><br><span class="line">    print(<span class="string">&quot;结束处理reqB&quot;</span>)</span><br></pre></td></tr></table></figure><ol start="6"><li>程序入口函数</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>():</span></span><br><span class="line">    reqA()</span><br><span class="line">    reqB()</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        time.sleep(<span class="number">0.1</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure><p>以后我们不用谢这么复杂的装饰器了,tornado已经帮我们写好了,你只要有异步就用装饰器来装饰一下就OK,其他的都不需要写</p><p>tornado里面指正不是这么写代码,不然要是这样写,你们全费了,tornado留下的都是简单易用的</p><p>这玩意不是你理解不理解,你一开始指定是不理解,你多用才能懂里面的原理</p><p>这个协程中的异步,其实他本质上不是协程,以为他用了多个线程,因为协程的定义是在一个线程里面玩的,只是来理解tornado实现原理</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> tornado </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tornado学习笔记day08</title>
      <link href="python/tornado/tornado-note8/"/>
      <url>python/tornado/tornado-note8/</url>
      
        <content type="html"><![CDATA[<h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p>应为epoll主要用来解决网络的并发问题,所以tornado中的异步也是主要体现在网络的IO异步上,即异步web请求</p><h3 id="tornado-httpclient-AsyncHTTPClient"><a href="#tornado-httpclient-AsyncHTTPClient" class="headerlink" title="tornado.httpclient.AsyncHTTPClient"></a>tornado.httpclient.AsyncHTTPClient</h3><p>tornado提供异步web请求客户端,可以用来进行异步web请求,<br>这个客户端和服务端是相对来说的,当tornado的Handler去其他位置去请求资源的时候,他就是客户端</p><h3 id="fetch-request-callback-None"><a href="#fetch-request-callback-None" class="headerlink" title="fetch(request, callback=None)"></a>fetch(request, callback=None)</h3><p>用于执行一个web请求,并异步响应返回一个tornado.httpclient.httpresponse<br>request可以是一个url,也可以是一个tornado.httpclient.httprequest对象<br>如果插入的是url会自动生成一个request对象</p><h3 id="HTTPRequest"><a href="#HTTPRequest" class="headerlink" title="HTTPRequest"></a>HTTPRequest</h3><h4 id="概述-1"><a href="#概述-1" class="headerlink" title="概述"></a>概述</h4><p>HTTP请求类,该类的构造函数可以接收参数</p><h4 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h4><ul><li>url: 字符串类型,要访问的网址,必传</li><li>method: 字符串类型,HTTP请求方式</li><li>headers: 字典类型,或者HTTPHeaders类型</li><li>body: HTTP请求体</li></ul><h3 id="HTTPResponse"><a href="#HTTPResponse" class="headerlink" title="HTTPResponse"></a>HTTPResponse</h3><h4 id="响应类"><a href="#响应类" class="headerlink" title="响应类"></a>响应类</h4><h4 id="属性"><a href="#属性" class="headerlink" title="属性"></a>属性</h4><ul><li>code: 状态码</li><li>reason: 状态码的描述</li><li>body: 响应的数据</li><li>error: 异常<h3 id="tornado-web-asynchronous"><a href="#tornado-web-asynchronous" class="headerlink" title="@tornado.web.asynchronous"></a>@tornado.web.asynchronous</h3>不关闭通讯的通道<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;tornado 6之后弃用&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="meta">@tornado.web.asynchronous</span></span><br><span class="line">改成</span><br><span class="line"><span class="meta">@tornado.gen.coroutine</span></span><br></pre></td></tr></table></figure><h3 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h3><h4 id="回调函数实现异步"><a href="#回调函数实现异步" class="headerlink" title="回调函数实现异步"></a>回调函数实现异步</h4>代码示例</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Students1Handler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_response</span>(<span class="params">self,response</span>):</span></span><br><span class="line">        print(<span class="string">&quot;刚进到on_response里面n&quot;</span>)</span><br><span class="line">        <span class="keyword">if</span> response.error:</span><br><span class="line">            self.send_error(<span class="number">500</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;开始获取data&quot;</span>)</span><br><span class="line">            data = json.loads(response.body)</span><br><span class="line">            print(<span class="string">&quot;data获取成功&quot;</span>)</span><br><span class="line">            self.write(data)</span><br><span class="line">            print(<span class="string">&quot;data写入成功&quot;</span>)</span><br><span class="line">        self.finish()</span><br><span class="line"></span><br><span class="line"><span class="meta">    @tornado.gen.coroutine</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 获取所有学生的信息</span></span><br><span class="line">        <span class="comment"># time.sleep(30)</span></span><br><span class="line">        <span class="comment"># 创建客户端</span></span><br><span class="line">        url = <span class="string">&quot;http://127.0.0.1:8080/home&quot;</span></span><br><span class="line">        print(<span class="string">&quot;url是&quot;</span>,url)</span><br><span class="line">        client = AsyncHTTPClient()</span><br><span class="line">        print(<span class="string">&quot;客户端创建成功&quot;</span>)</span><br><span class="line">        client.fetch(url, self.on_response)</span><br><span class="line"></span><br><span class="line">        self.write(<span class="string">&quot;students info content!&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HomeHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 获取所有学生的信息</span></span><br><span class="line">        self.write(<span class="string">&quot;homo page info!&quot;</span>)</span><br></pre></td></tr></table></figure><h4 id="协程实现异步"><a href="#协程实现异步" class="headerlink" title="协程实现异步"></a>协程实现异步</h4><p>代码示例1</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Students2Handler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line"><span class="meta">    @tornado.gen.coroutine</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self, *args, **kwargs</span>):</span></span><br><span class="line">        url = <span class="string">&quot;http://s.budejie.com/topic/tag-topic/64/hot/budejie-android-6.6.9/0-20.json?market=xiaomi&amp;ver=6.6.9&amp;visiting=&amp;os=7.1.1&amp;appname=baisibudejie&amp;client=android&amp;udid=863254032906009&amp;mac=02%3A00%3A00%3A00%3A00%3A00&quot;</span></span><br><span class="line">        client = AsyncHTTPClient()</span><br><span class="line">        res = <span class="keyword">yield</span> client.fetch(url)</span><br><span class="line">        <span class="keyword">if</span> res.error:</span><br><span class="line">            self.send_error(<span class="number">500</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            data = json.loads(res.body)</span><br><span class="line">            self.write(data)</span><br></pre></td></tr></table></figure><p>代码示例2 , 将异步web请求单独分离出来</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Students3Handler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line"><span class="meta">    @tornado.gen.coroutine</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self, *args, **kwargs</span>):</span></span><br><span class="line">        res = <span class="keyword">yield</span> self.getData()</span><br><span class="line">        self.write(res)</span><br><span class="line"></span><br><span class="line"><span class="meta">    @tornado.gen.coroutine</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getData</span>(<span class="params">self</span>):</span></span><br><span class="line">        url = <span class="string">&quot;http://s.budejie.com/topic/tag-topic/64/hot/budejie-android-6.6.9/0-20.json?market=xiaomi&amp;ver=6.6.9&amp;visiting=&amp;os=7.1.1&amp;appname=baisibudejie&amp;client=android&amp;udid=863254032906009&amp;mac=02%3A00%3A00%3A00%3A00%3A00&quot;</span></span><br><span class="line">        client = AsyncHTTPClient()</span><br><span class="line">        res = <span class="keyword">yield</span> client.fetch(url)</span><br><span class="line">        <span class="keyword">if</span> res.error:</span><br><span class="line">            ret = &#123;<span class="string">&quot;ret&quot;</span>:<span class="number">0</span>&#125;</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            ret = json.loads(res.body)</span><br><span class="line">        <span class="keyword">raise</span> tornado.gen.Return(ret)</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HomeHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 获取所有学生的信息</span></span><br><span class="line">        self.write(<span class="string">&quot;homo page info!&quot;</span>)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> tornado </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tornado学习笔记day06</title>
      <link href="python/tornado/tornado-note6/"/>
      <url>python/tornado/tornado-note6/</url>
      
        <content type="html"><![CDATA[<h1 id="应用安全"><a href="#应用安全" class="headerlink" title="应用安全"></a>应用安全</h1><h3 id="cookie"><a href="#cookie" class="headerlink" title="cookie"></a>cookie</h3><h5 id="普通cookie"><a href="#普通cookie" class="headerlink" title="普通cookie"></a>普通cookie</h5><p>一般我们的用户表中都有啥呢</p><p>你在购物的时候,加入购物车,让你登录,那你登录之后,他怎么知道你登录了呢</p><p>token 这个值是随机的,存在<code>cookie</code>里面</p><h6 id="设置"><a href="#设置" class="headerlink" title="设置"></a>设置</h6><ul><li>原型: 设置<code>cookie</code> 的方法<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">set_cookie</span>(<span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">    self,</span></span></span><br><span class="line"><span class="function"><span class="params">    name: <span class="built_in">str</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    value: Union[<span class="built_in">str</span>, <span class="built_in">bytes</span>],</span></span></span><br><span class="line"><span class="function"><span class="params">    domain: <span class="built_in">str</span> = <span class="literal">None</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    expires: Union[<span class="built_in">float</span>, Tuple, datetime.datetime] = <span class="literal">None</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    path: <span class="built_in">str</span> = <span class="string">&quot;/&quot;</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    expires_days: <span class="built_in">int</span> = <span class="literal">None</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    **kwargs: Any</span>) -&gt; <span class="keyword">None</span>:</span></span><br></pre></td></tr></table></figure></li><li>参数<ul><li>name:我们设置的<code>cookie</code>的名字</li><li>value:cookie的值</li><li>domain:提交<code>cookie</code>时匹配的域名,也就是哪个ip拿过来的</li><li>path:提交<code>cookie</code>时匹配的路径</li><li>expires:设置<code>cookie</code>的有效期,可以是时间磋整数,时间元组,<code>datetime</code>类型,为UTC时间</li><li>expires_days:设置cookie的有效期(天数)但是他的优先级低于expires</li></ul></li><li>实例:</li></ul><h6 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h6><p>设置<code>cookie</code>实际上是通过设置<code>header</code>的<code>Set-Cookie</code>来实现的</p><h6 id="获取"><a href="#获取" class="headerlink" title="获取"></a>获取</h6><p>我们设置完了就要获取,为什么要获取呢,因为以后我们在发送请求就要携带着这个cookie了</p><ul><li>原型:<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_cookie</span>(<span class="params">self, name: <span class="built_in">str</span>, default: <span class="built_in">str</span> = <span class="literal">None</span></span>) -&gt; Optional[str]:</span></span><br></pre></td></tr></table></figure></li><li>参数:<ul><li>name:要获取的cookie 的名称</li><li>default:如果名为name的获取的cookie不存在,就走这个默认值了</li></ul></li><li>示例:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cookie = self.get_cookie(<span class="string">&quot;suck&quot;</span>,<span class="string">&quot;未登录&quot;</span>)</span><br><span class="line">print(cookie)</span><br><span class="line">self.write(<span class="string">&quot;getcookie page info tornado!&quot;</span>)</span><br><span class="line">self.write(cookie)</span><br></pre></td></tr></table></figure><h6 id="清除"><a href="#清除" class="headerlink" title="清除"></a>清除</h6><ul><li>原型:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">clear_cookie</span>(<span class="params">self, name: <span class="built_in">str</span>, path: <span class="built_in">str</span> = <span class="string">&quot;/&quot;</span>, domain: <span class="built_in">str</span> = <span class="literal">None</span></span>) -&gt; <span class="keyword">None</span>:</span></span><br></pre></td></tr></table></figure><ul><li>作用:<ul><li>删除名为<code>name</code> 的<code>cookie</code>,并同时匹配<code>domain</code>和<code>path</code>的<code>cookie</code></li><li>哟时候有可能这个name相同啊,那这个时候就得用path和domain来匹配一下了</li></ul></li><li>注意: <ul><li>执行cookie删除后,并不是直接就删除了,</li><li>而是给cookie设置内容为null空,并删除延迟时间,</li><li>真正删除是浏览器自己清理的,浏览器发现他没有用的话就给他删掉了,就看浏览器的了 </li></ul></li><li>还有一个原型:<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">clear_all_cookies</span>(<span class="params">self, path: <span class="built_in">str</span> = <span class="string">&quot;/&quot;</span>, domain: <span class="built_in">str</span> = <span class="literal">None</span></span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">```   </span><br><span class="line">- 作用:删除同时匹配path和domain的所有cookie    </span><br><span class="line">- 示例:</span><br><span class="line">```python</span><br><span class="line"><span class="comment"># 清除cookie</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ClearPCookieHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 这个删除cookie后,他这次不能决定</span></span><br><span class="line">        <span class="comment"># 是下一次删除了</span></span><br><span class="line">        <span class="comment"># 清除一个cookie</span></span><br><span class="line">        self.clear_cookie(<span class="string">&quot;suck&quot;</span>)</span><br><span class="line">        <span class="comment"># 清除所有cookie</span></span><br><span class="line">        self.clear_all_cookies()</span><br><span class="line">        self.write(<span class="string">&quot;ClearPCookieHandler page info tornado!&quot;</span>)</span><br></pre></td></tr></table></figure><h5 id="安全cookie"><a href="#安全cookie" class="headerlink" title="安全cookie"></a>安全cookie</h5><h6 id="概述"><a href="#概述" class="headerlink" title="概述:"></a>概述:</h6>cookie是存储在客户端浏览器的数据,很容易被篡改,不是很安全</li></ul><p>tornado提供了一种对于cookie简易的加密的方法,来防止cookie被恶意篡改</p><h6 id="设置-1"><a href="#设置-1" class="headerlink" title="设置:"></a>设置:</h6><ul><li>需要为应用配置的进行混淆加密的秘钥  </li><li>生成一个秘钥:<br>我们需要用到一个库<code>base64</code>,你需要知道的就是他是加密的就行了,是一个唯一的标识,其他的你就不用管了,因为其他的你想管你也管不着了<br>md5 现在已经不安全了,现在有一些网站已经能够在线破解md5了</li></ul><p>我们在python控制台输入如下代码,即可生成一个uuid    </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">base64.b64encode(uuid.uuid4().<span class="built_in">bytes</span>+uuid.uuid4().<span class="built_in">bytes</span>)</span><br><span class="line"><span class="string">b&#x27;j94bbx0zSY6yYkCgawwJ1bzyM4jzDUuKtLyPC/MMmZA=&#x27;</span></span><br></pre></td></tr></table></figure><p>我们需要在配置文件config.py中进行配置<br>内容如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">settings = &#123;</span><br><span class="line">    <span class="comment"># 这写key的名字可不是随便起的奥,是写好的,</span></span><br><span class="line">    <span class="comment"># 就像upfile就没有,你写了也白扯</span></span><br><span class="line">    <span class="string">&#x27;template_path&#x27;</span>: os.path.join(BASE_DIR, <span class="string">&quot;templates&quot;</span>),</span><br><span class="line">    <span class="string">&#x27;static_path&#x27;</span>: os.path.join(BASE_DIR, <span class="string">&quot;static&quot;</span>),</span><br><span class="line">    <span class="string">&quot;debug&quot;</span>: <span class="literal">True</span>,</span><br><span class="line">    <span class="comment"># &quot;autoreload&quot; : True</span></span><br><span class="line">    <span class="string">&quot;cookie_secret&quot;</span>:<span class="string">&quot;j94bbx0zSY6yYkCgawwJ1bzyM4jzDUuKtLyPC/MMmZA=&quot;</span>,</span><br><span class="line">    <span class="comment"># 这个据说一百亿年才能,用完</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后给你看一个方法,他的原型如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">set_secure_cookie</span>(<span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">    self,</span></span></span><br><span class="line"><span class="function"><span class="params">    name: <span class="built_in">str</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    value: Union[<span class="built_in">str</span>, <span class="built_in">bytes</span>],</span></span></span><br><span class="line"><span class="function"><span class="params">    expires_days: <span class="built_in">int</span> = <span class="number">30</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    version: <span class="built_in">int</span> = <span class="literal">None</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    **kwargs: Any</span></span></span><br><span class="line"><span class="function"><span class="params"></span>) -&gt; <span class="keyword">None</span>:</span></span><br></pre></td></tr></table></figure><p>作用:设置一个带有签名和时间戳的cookie,防止cookie被伪造</p><p>实际上是这样写的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安全cookie</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SCookieHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.set_secure_cookie(<span class="string">&quot;victor&quot;</span>,<span class="string">&quot;nice&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;SCookieHandler page info tornado!&quot;</span>)</span><br></pre></td></tr></table></figure><p>然后我们在浏览器中查看一下cookie的值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Set-Cookie: victor=<span class="string">&quot;2|1:0|10:1575853257|6:victor|8:bmljZQ</span></span><br><span class="line"><span class="string">==|ac4c19c8598fc7c7d07c1484f07a0cc8e1a1adb022d084bcc3d3d4</span></span><br><span class="line"><span class="string">75129fab63&quot;</span>; expires=Wed, 08 Jan <span class="number">2020</span> 01:<span class="number">00</span>:<span class="number">57</span> GMT; Path=/</span><br></pre></td></tr></table></figure><p>现在这个值,你看不出来内容是啥了<br>说明:</p><ul><li>安全cookie版本,默认使用2</li><li>默认为0</li><li>时间戳</li><li>cookie名</li><li>base64cookie编码的值</li><li>签名值(不带长度说明)<h6 id="获取-1"><a href="#获取-1" class="headerlink" title="获取:"></a>获取:</h6>直接就把原型往这里一扔<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_secure_cookie</span>(<span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">    self,</span></span></span><br><span class="line"><span class="function"><span class="params">    name: <span class="built_in">str</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    value: <span class="built_in">str</span> = <span class="literal">None</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    max_age_days: <span class="built_in">int</span> = <span class="number">31</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    min_version: <span class="built_in">int</span> = <span class="literal">None</span>,</span></span></span><br><span class="line"><span class="function"><span class="params"></span>) -&gt; Optional[bytes]:</span></span><br></pre></td></tr></table></figure>然后我这么写<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 获取安全cookie</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GetSCookieHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        sc = self.get_secure_cookie(<span class="string">&quot;victor&quot;</span>)</span><br><span class="line">        print(sc)</span><br><span class="line">        self.write(<span class="string">&quot;getSCookieHandler page info tornado!&quot;</span>)</span><br><span class="line">        self.write(sc)</span><br></pre></td></tr></table></figure>如果cookie验证通过,就会返回这个cookie的值,否则返回None</li></ul><p>max_age_days不同于expries_days设置的浏览器中cookie的有效时间<br>而max_age_days是过滤安全cookie的时间戳,默认是31天</p><h6 id="注意"><a href="#注意" class="headerlink" title="注意:"></a>注意:</h6><ul><li>这个安全cookie,也不是绝对安全的,只是一定程度上增加了破解的难度</li><li>以后cookie中不要存储一些敏感性的数据</li></ul><h3 id="XSRF"><a href="#XSRF" class="headerlink" title="XSRF"></a>XSRF</h3><h4 id="跨站请求伪造代码"><a href="#跨站请求伪造代码" class="headerlink" title="跨站请求伪造代码"></a>跨站请求伪造代码</h4><p>示例:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># cookie计数</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CookieNumHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        count = self.get_cookie(<span class="string">&quot;count&quot;</span>,<span class="literal">None</span>)</span><br><span class="line">        <span class="keyword">if</span> count:</span><br><span class="line">            <span class="comment"># 第n次访问</span></span><br><span class="line">            count = <span class="built_in">str</span>(<span class="built_in">int</span>(count)+<span class="number">1</span>)</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="comment"># 第一次访问</span></span><br><span class="line">            <span class="comment"># 设置cookie</span></span><br><span class="line">            count = <span class="string">&#x27;0&#x27;</span></span><br><span class="line">        self.set_cookie(<span class="string">&quot;count&quot;</span>,count)</span><br><span class="line"></span><br><span class="line">        self.render(<span class="string">&quot;cookienum.html&quot;</span>,count = count)</span><br></pre></td></tr></table></figure><p>页面是这个样子的:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>搞事情<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>第&#123; &#123; count &#125; &#125;次访问<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>搞事情网站,我就看看能不能搞坏!!!<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;http://127.0.0.1:8080/cookienum&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>当我们访问搞事情网站的时候,当我们不知情的时候,未授权的情况下,<code>cookie计数器</code>网站中的<code>cookie</code>被使用,导致<code>cookie计数器</code>网站认为是他自己调用了<code>Handler</code>逻辑</p><p>上一个程序使用的是GET方式模拟的攻击,为了防止这种攻击,一般对于相对安全的操作一般不放在GET请求中.</p><p>我们常常使用的是POST请求</p><h4 id="XSRF保护"><a href="#XSRF保护" class="headerlink" title="XSRF保护"></a>XSRF保护</h4><p>同源:同域名同协议同端口<br>只有同源才让他能访问</p><h4 id="开启保护"><a href="#开启保护" class="headerlink" title="开启保护"></a>开启保护</h4><p>在配置中添加</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;xsrf_cookies&quot;</span>:<span class="literal">True</span></span><br></pre></td></tr></table></figure><p>然后在这里别忘了也整一下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">super</span>(Application, self).__init__(</span><br><span class="line">    handlers,</span><br><span class="line">    <span class="comment"># 模板路径</span></span><br><span class="line">    template_path=settings[<span class="string">&quot;template_path&quot;</span>],</span><br><span class="line">    <span class="comment"># 静态路径</span></span><br><span class="line">    static_path=settings[<span class="string">&quot;static_path&quot;</span>],</span><br><span class="line">    <span class="comment"># cookie签名</span></span><br><span class="line">    cookie_secret=settings[<span class="string">&quot;cookie_secret&quot;</span>],</span><br><span class="line">    xsrf_cookies=settings[<span class="string">&quot;xsrf_cookies&quot;</span>],</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>现在保护一开,谁都别想访问了<br>那我们还要干什么?<br>我们怎么才能让我们自身的能够进行访问啊</p><h4 id="附加"><a href="#附加" class="headerlink" title="附加"></a>附加</h4><p>配置文件中的键和值不用一个一个写,直接就<code>**</code>打散就OK了</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 是不是傻了,这里直接就** 就行了</span></span><br><span class="line"><span class="built_in">super</span>(Application, self).__init__(</span><br><span class="line">    handlers,**settings</span><br><span class="line">)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h4><h5 id="在模板中应用"><a href="#在模板中应用" class="headerlink" title="在模板中应用"></a>在模板中应用</h5><h6 id="在form表单中加上这么一句话-模板里面就能用了"><a href="#在form表单中加上这么一句话-模板里面就能用了" class="headerlink" title="在form表单中加上这么一句话,模板里面就能用了"></a>在form表单中加上这么一句话,模板里面就能用了</h6><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123; % module xsrf_form_html() % &#125;</span><br></pre></td></tr></table></figure><h6 id="完整的就这样了"><a href="#完整的就这样了" class="headerlink" title="完整的就这样了"></a>完整的就这样了</h6><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Post page<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;/postfile&quot;</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span>&gt;</span></span><br><span class="line">        &#123; % module xsrf_form_html() % &#125;</span><br><span class="line">        姓名:<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span><br><span class="line">        密码:<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;password&quot;</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;登录&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h6 id="作用"><a href="#作用" class="headerlink" title="作用:"></a>作用:</h6><ul><li>为浏览器设置了<code>_xsrf</code>的安全<code>cookie</code>,这个<code>cookie</code>在关闭浏览器后就失效了</li><li>为模板添加了一个隐藏的输出,隐藏域,名为<code>_xsrf</code>,值为<code>_xsrf</code>这个<code>cookie</code>的值</li><li>表单中的一个隐藏域,名为…值为…,但是还是不绝对安全<h5 id="在非模板中应用"><a href="#在非模板中应用" class="headerlink" title="在非模板中应用"></a>在非模板中应用</h5></li></ul><h6 id="手动设置-xsrf的cookie"><a href="#手动设置-xsrf的cookie" class="headerlink" title="手动设置_xsrf的cookie"></a>手动设置_xsrf的cookie</h6><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;设置XsrfCookieHandler&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SetXsrfCookieHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 设置一个_xsrf的cookie</span></span><br><span class="line">        self.xsrf_token</span><br><span class="line">        self.finish(<span class="string">&quot;OK&quot;</span>)</span><br></pre></td></tr></table></figure><h6 id="第一种"><a href="#第一种" class="headerlink" title="第一种"></a>第一种</h6><ul><li>我们可以不在页面中写那一行代码  而是写一个<code>script</code>的JS代码,其中实现手动的添加一个隐藏<code>input</code></li><li>手动创建<code>input</code>,并设置name的属性值为<code>_xsrf</code>,<code>value</code>的属性值为名为<code>_xsrf</code>的cookie的值</li></ul><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Post page<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;/postfile&quot;</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">id</span>=<span class="string">&quot;hi&quot;</span> <span class="attr">type</span>=<span class="string">&quot;hidden&quot;</span> <span class="attr">name</span>=<span class="string">&quot;_xsrf&quot;</span> <span class="attr">value</span>=<span class="string">&quot;&quot;</span>&gt;</span></span><br><span class="line">        姓名:<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span><br><span class="line">        密码:<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;password&quot;</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;登录&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="keyword">function</span> <span class="title">getCookie</span>(<span class="params">name</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">            <span class="comment">// 这里写的就不用管他是啥意思了</span></span></span><br><span class="line"><span class="javascript">            <span class="keyword">var</span> cook = <span class="built_in">document</span>.cookie.match(<span class="string">&quot;\\b&quot;</span> + name + <span class="string">&quot;=([^;]*)\\b&quot;</span>);</span></span><br><span class="line"><span class="javascript">            <span class="comment">// 我们要返回的是cookie,不是cook</span></span></span><br><span class="line"><span class="javascript">            <span class="comment">// 如果有,那我就拿他的第一个值,就是这个cookie值</span></span></span><br><span class="line"><span class="javascript">            <span class="keyword">return</span> cook ? cook[<span class="number">1</span>] : <span class="literal">undefined</span></span></span><br><span class="line">        &#125;</span><br><span class="line"><span class="javascript">        <span class="comment">// 获取cookie</span></span></span><br><span class="line"><span class="javascript">        gc = getCookie(<span class="string">&quot;_xsrf&quot;</span>);</span></span><br><span class="line"><span class="javascript">        <span class="built_in">console</span>.log(gc);</span></span><br><span class="line"><span class="javascript">        <span class="built_in">document</span>.getElementById(<span class="string">&quot;hi&quot;</span>).value = gc;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h6 id="第二种"><a href="#第二种" class="headerlink" title="第二种"></a>第二种</h6><p>发起ajax请求:<br>我们把这个表单去掉,然后在js中点击这个按钮就发起ajax请求<br>我们没有学过原生的ajax吧!那么就需要借助jQuery了吧!</p><p>具体代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Post page<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--    导入jQuery--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> <span class="attr">src</span>=<span class="string">&quot;&#123;&#123;static_url(&#x27;js/jquery.min.js&#x27;)&#125;&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">id</span>=<span class="string">&quot;hi&quot;</span> <span class="attr">type</span>=<span class="string">&quot;hidden&quot;</span> <span class="attr">name</span>=<span class="string">&quot;_xsrf&quot;</span> <span class="attr">value</span>=<span class="string">&quot;&quot;</span>&gt;</span></span><br><span class="line">姓名:<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span><br><span class="line">密码:<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;password&quot;</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;登录&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> <span class="attr">id</span>=<span class="string">&quot;btn&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;login()&quot;</span>&gt;</span>登录<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">getCookie</span>(<span class="params">name</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 这里写的就不用管他是啥意思了</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">var</span> cook = <span class="built_in">document</span>.cookie.match(<span class="string">&quot;\\b&quot;</span> + name + <span class="string">&quot;=([^;]*)\\b&quot;</span>);</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 我们要返回的是cookie,不是cook</span></span></span><br><span class="line"><span class="javascript">        <span class="comment">// 如果有,那我就拿他的第一个值,就是这个cookie值</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> cook ? cook[<span class="number">1</span>] : <span class="literal">undefined</span></span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">login</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 发起ajax请求我们有很多种方式</span></span></span><br><span class="line"><span class="javascript">        <span class="comment">// 发起post请求我们有两种方式,一种是这个</span></span></span><br><span class="line"><span class="javascript">        $.post(<span class="string">&quot;/postfile&quot;</span>,</span></span><br><span class="line"><span class="javascript">            <span class="string">&quot;_xsrf=&quot;</span> + getCookie(<span class="string">&quot;_xsrf&quot;</span>) + <span class="string">&quot;&amp;username=&quot;</span> + <span class="string">&quot;victor&quot;</span> + <span class="string">&quot;&amp;passwd=&quot;</span> + <span class="string">&quot;123456&quot;</span>,</span></span><br><span class="line"><span class="javascript">            <span class="comment">// 请求成功后的回调函数</span></span></span><br><span class="line"><span class="javascript">            <span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                alert(<span class="string">&quot;ok\\(^o^)/~&quot;</span>);</span></span><br><span class="line">                alert(data);</span><br><span class="line">            &#125;</span><br><span class="line">        );</span><br><span class="line"><span class="javascript">        <span class="comment">// TODO 其实这里要通过DOM元素获取username,和passwd的值的,</span></span></span><br><span class="line"><span class="javascript">        <span class="comment">// TODO 因为这里不是作为重点就写了</span></span></span><br><span class="line">        /**</span><br><span class="line">         * 这里主要是要带着这个xsrf防护,不然这个是不能给你响应的</span><br><span class="line">         */</span><br><span class="line">    &#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h6 id="第三种"><a href="#第三种" class="headerlink" title="第三种"></a>第三种</h6><p>其实这种才是最常用的方式,这个<code>$.post</code>仅仅只能发起post请求,所携带的参数或者说对于他的控制是比较少的<br><code>$.ajax</code>才是最NB的方式</p><p>来吧!直接就上代码</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Post page<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--    导入jQuery--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> <span class="attr">src</span>=<span class="string">&quot;&#123;&#123;static_url(&#x27;js/jquery.min.js&#x27;)&#125;&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">id</span>=<span class="string">&quot;hi&quot;</span> <span class="attr">type</span>=<span class="string">&quot;hidden&quot;</span> <span class="attr">name</span>=<span class="string">&quot;_xsrf&quot;</span> <span class="attr">value</span>=<span class="string">&quot;&quot;</span>&gt;</span></span><br><span class="line">姓名:<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span><br><span class="line">密码:<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;password&quot;</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;登录&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> <span class="attr">id</span>=<span class="string">&quot;btn&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;login()&quot;</span>&gt;</span>登录<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">getCookie</span>(<span class="params">name</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 这里写的就不用管他是啥意思了</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">var</span> cook = <span class="built_in">document</span>.cookie.match(<span class="string">&quot;\\b&quot;</span> + name + <span class="string">&quot;=([^;]*)\\b&quot;</span>);</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 我们要返回的是cookie,不是cook</span></span></span><br><span class="line"><span class="javascript">        <span class="comment">// 如果有,那我就拿他的第一个值,就是这个cookie值</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> cook ? cook[<span class="number">1</span>] : <span class="literal">undefined</span></span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">login</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="comment">// TODO 这块还是那么回事,数据可以通过DOM来动态获取</span></span></span><br><span class="line">        data = &#123;</span><br><span class="line"><span class="javascript">            <span class="string">&quot;username&quot;</span>: <span class="string">&quot;victor&quot;</span>,</span></span><br><span class="line"><span class="javascript">            <span class="string">&quot;passwd&quot;</span>: <span class="string">&quot;123456&quot;</span>,</span></span><br><span class="line">            &#125;;</span><br><span class="line"><span class="javascript">        <span class="comment">// 我们需要把我们的数据给他变成一个字符串</span></span></span><br><span class="line"><span class="javascript">        <span class="comment">// 这个方法是JS中的东西,不是python,jQuery的</span></span></span><br><span class="line"><span class="javascript">        <span class="keyword">var</span> data_str = <span class="built_in">JSON</span>.stringify(data);</span></span><br><span class="line"><span class="javascript">        <span class="comment">// 这个ajax怎么写呢?,他里面就一个参数,就是一个字典</span></span></span><br><span class="line"><span class="javascript">        $.ajax(&#123;</span></span><br><span class="line"><span class="javascript">            url: <span class="string">&quot;/postfile&quot;</span>,</span></span><br><span class="line"><span class="javascript">            <span class="comment">// 这个请求方式你写啥,他就是啥,他都能发</span></span></span><br><span class="line"><span class="javascript">            method: <span class="string">&quot;POST&quot;</span>,</span></span><br><span class="line">            data: data_str,</span><br><span class="line"><span class="javascript">            <span class="comment">// 你看吧这个字典中的一个键里面对应的值是函数,</span></span></span><br><span class="line"><span class="javascript">            <span class="comment">// 虽然外面就一个字典类型的参数,但是回调函数还是有的</span></span></span><br><span class="line"><span class="javascript">            success: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                alert(<span class="string">&quot;ok!!!&quot;</span>)</span></span><br><span class="line">            &#125;,</span><br><span class="line"><span class="javascript">            <span class="comment">// 到这里绝壁是不能成功的,因为我这个_xsrf都没写怎么能成功呢</span></span></span><br><span class="line"><span class="javascript">            <span class="comment">// 如果想发起请求,我们还需要添加一个headers,也就是请求头</span></span></span><br><span class="line">            headers:&#123;</span><br><span class="line"><span class="javascript">                <span class="comment">// 来这个跟着写就对了</span></span></span><br><span class="line"><span class="javascript">                <span class="comment">// 这个值就设置成之前那个cookie值就行了</span></span></span><br><span class="line"><span class="javascript">                <span class="string">&quot;X-XSRFToken&quot;</span>: getCookie(<span class="string">&quot;_xsrf&quot;</span>),</span></span><br><span class="line">            &#125;,</span><br><span class="line">        &#125;)</span><br><span class="line"><span class="javascript">        <span class="comment">// 以后发起ajax请求,建议使用这个,功能更加强大</span></span></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h6 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h6><p>其实帅的人是不会用第一种方式写的</p><p>需要手动<a href="https://victorfengming.gitee.io/blog/tornado-note6/#%E6%89%8B%E5%8A%A8%E8%AE%BE%E7%BD%AE_xsrf%E7%9A%84cookie">设置token</a><br>解决:其实一般我们进入一个网站的时候,通常是不是都先进入主页啊,你进入主页的时候就把这个<code>xsrf</code>写进去了</p><p>首先我们添加一个进入主页的静态默认页面</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">(</span><br><span class="line">    <span class="string">r&quot;/(.*)$&quot;</span>,</span><br><span class="line">    <span class="comment"># 系统这个我们不能用,所以我们继承,</span></span><br><span class="line">    <span class="comment"># tornado.web.StaticFileHandler,</span></span><br><span class="line">    <span class="comment"># 让我们自己写这个继承自系统给我们这个</span></span><br><span class="line">    index.MyStaticFileHandler,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="string">&quot;path&quot;</span>: os.path.join(BASE_DIR, <span class="string">&quot;static/html&quot;</span>),</span><br><span class="line">        <span class="string">&quot;default_filename&quot;</span>: <span class="string">&quot;index.html&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">),</span><br></pre></td></tr></table></figure><p>然后重写StaticFileHandler</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> tornado.web <span class="keyword">import</span> StaticFileHandler</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置静态默认</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyStaticFileHandler</span>(<span class="params">StaticFileHandler</span>):</span></span><br><span class="line">    <span class="comment"># 我们用他的时候只需要重写他的init就可以了</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self,*args,**kwargs</span>):</span></span><br><span class="line">        <span class="built_in">super</span>(MyStaticFileHandler,self).__init__(*args,**kwargs)</span><br><span class="line">        self.xsrf_token</span><br></pre></td></tr></table></figure><h5 id="补充"><a href="#补充" class="headerlink" title="补充"></a>补充</h5><ul><li>_xsrf 加一个下划线,我们把他看成是私有的  </li><li>__xsrf就真的是私有的了<h3 id="用户验证"><a href="#用户验证" class="headerlink" title="用户验证"></a>用户验证</h3><h4 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h4>在收到用户请求后,进行一个预先判断用户的认证状态(是否登录),若验证通过正常处理,否则进入登录界面去,滚去登录</li></ul><h4 id="tornado-web-authenticate-装饰器"><a href="#tornado-web-authenticate-装饰器" class="headerlink" title="tornado.web.authenticate 装饰器"></a>tornado.web.authenticate 装饰器</h4><p>tornado将确保这个方法的主体(他修饰的东西)只有合法的用户才能调用</p><h4 id="get-current-user"><a href="#get-current-user" class="headerlink" title="get_current_user"></a>get_current_user</h4><p>我们自己定义一个方法<code>get_current_user()</code><br>功能:验证用户的逻辑,应该写在该方法中,<br>如果该方法返回的为True说明验证成功,否则验证失败<br>验证失败:访客重定向到配置中的所制定的路由(登录界面)<br>需要在配置文件<code>config.py</code>中写上配置的位置,因为你不一定要跳转到登录界面吧!</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;login_url&quot;</span>:<span class="string">&quot;/login&quot;</span>,</span><br></pre></td></tr></table></figure><p>这样你要是没登录,他就给你踢到那个页面中了</p><p>然后直接就上代码</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;首先 路由是这样的 &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 登录界面</span></span><br><span class="line">tornado.web.url(<span class="string">r&quot;/login&quot;</span>, index.LoginHandler,name=<span class="string">&#x27;login&#x27;</span>),</span><br><span class="line"><span class="comment"># home页面</span></span><br><span class="line">(<span class="string">r&quot;/home&quot;</span>, index.HomeHandler),</span><br><span class="line"><span class="comment"># 一个无名的普通页面,用于测试的</span></span><br><span class="line">(<span class="string">r&quot;/cart&quot;</span>, index.CartHandler),</span><br><span class="line"></span><br><span class="line">(</span><br><span class="line">    <span class="string">r&quot;/(.*)$&quot;</span>,</span><br><span class="line">    <span class="comment"># 系统这个我们不能用,所以我们继承,</span></span><br><span class="line">    <span class="comment"># tornado.web.StaticFileHandler,</span></span><br><span class="line">    <span class="comment"># 让我们自己写这个继承自系统给我们这个</span></span><br><span class="line">    index.MyStaticFileHandler,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="string">&quot;path&quot;</span>: os.path.join(BASE_DIR, <span class="string">&quot;static/html&quot;</span>),</span><br><span class="line">        <span class="string">&quot;default_filename&quot;</span>: <span class="string">&quot;index.html&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">),</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;登录页面&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LoginHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 进入登录我就要知道我是从哪里进的了</span></span><br><span class="line">        <span class="built_in">next</span> = self.get_argument(<span class="string">&quot;next&quot;</span>,<span class="string">&quot;/&quot;</span>)</span><br><span class="line">        url = <span class="string">&quot;login&quot;</span> + <span class="string">&quot;?next=&quot;</span> + <span class="built_in">next</span></span><br><span class="line">        self.render(<span class="string">&quot;login.html&quot;</span>, url=url)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">post</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        咱也不用管是get还是post了</span></span><br><span class="line"><span class="string">        name = self.get_body_argument(&quot;username&quot;)</span></span><br><span class="line"><span class="string">        passwd = self.get_body_argument(&quot;passwd&quot;)</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 直接我就写</span></span><br><span class="line">        name = self.get_argument(<span class="string">&quot;username&quot;</span>)</span><br><span class="line">        passwd = self.get_argument(<span class="string">&quot;passwd&quot;</span>)</span><br><span class="line">        <span class="comment"># TODO 这里还是把账号和密码写死了</span></span><br><span class="line">        <span class="keyword">if</span> name == <span class="string">&quot;victor&quot;</span> <span class="keyword">and</span> passwd == <span class="string">&quot;123456&quot;</span>:</span><br><span class="line">            <span class="comment"># 这个玩意代表从哪个页面跳来的,处理完了</span></span><br><span class="line">            <span class="comment"># 要是没毛病,我还得给你发到那里去</span></span><br><span class="line">            <span class="built_in">next</span> = self.get_argument(<span class="string">&quot;next&quot;</span>, <span class="string">&quot;/&quot;</span>)</span><br><span class="line">            <span class="comment"># 后面&quot;/&quot;是默认值</span></span><br><span class="line">            <span class="comment"># 重定向走你,但是光重定向不行</span></span><br><span class="line">            <span class="comment"># 我们还得加一个标记</span></span><br><span class="line">            self.redirect(<span class="built_in">next</span> + <span class="string">&quot;?flag=logined&quot;</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="built_in">next</span> = self.get_argument(<span class="string">&quot;next&quot;</span>, <span class="string">&quot;/&quot;</span>)</span><br><span class="line">            <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">            # 验证失败了,</span></span><br><span class="line"><span class="string">            # 路由的反向解析,听着挺高大上的</span></span><br><span class="line"><span class="string">            # 密码输入错误,好几次也得记着人家是从哪里过来的</span></span><br><span class="line"><span class="string">            &#x27;&#x27;&#x27;</span></span><br><span class="line">            log = self.reverse_url(<span class="string">&quot;login&quot;</span>)+<span class="string">&quot;?next=&quot;</span>+<span class="built_in">next</span></span><br><span class="line">            <span class="comment"># 我还是得重定向</span></span><br><span class="line">            self.redirect(log)</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27; 这个是主页面 &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HomeHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_current_user</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        # 返回True代表验证成功,否则凉凉</span></span><br><span class="line"><span class="string">        # return False</span></span><br><span class="line"><span class="string">        # 然后我们这里就能通过之前的flag来判断了</span></span><br><span class="line"><span class="string">        # 这里还要设置一个默认值否则就是</span></span><br><span class="line"><span class="string">        # WARNING:tornado.general:400 GET /home (127.0.0.1):</span></span><br><span class="line"><span class="string">                  Missing argument flag</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        flag = self.get_argument(<span class="string">&quot;flag&quot;</span>, <span class="literal">None</span>)</span><br><span class="line">        <span class="comment"># 如果能取到flag,就返回true</span></span><br><span class="line">        <span class="comment"># 要是娶不到,自然就返回False</span></span><br><span class="line">        <span class="keyword">return</span> flag</span><br><span class="line"></span><br><span class="line"><span class="meta">    @tornado.web.authenticated</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.render(<span class="string">&quot;home.html&quot;</span>)</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27; 这个cart是一个普通的页面&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CartHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_current_user</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">return</span> self.get_argument(<span class="string">&quot;flag&quot;</span>, <span class="literal">None</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">    @tornado.web.authenticated</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.render(<span class="string">&quot;cart.html&quot;</span>)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> tornado </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>rst文件是什么鬼?</title>
      <link href="python/collection/python-rst/"/>
      <url>python/collection/python-rst/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.jianshu.com/p/1885d5570b37">https://www.jianshu.com/p/1885d5570b37</a></p><p><strong>reStructuredText</strong> 是扩展名为.rst的纯文本文件，含义为"重新构建的文本"，也被简称为：RST或reST；是Python编程语言的Docutils项目的一部分，Python    Doc-SIG (Documentation Special Interest Group)。该项目类似于Java的JavaDoc或Perl的POD项目。 Docutils    能够从Python程序中提取注释和信息，格式化成程序文档。</p><p>.rst    文件是轻量级标记语言的一种，被设计为容易阅读和编写的纯文本，并且可以借助Docutils这样的程序进行文档处理，也可以转换为HTML或PDF等多种格式，或由Sphinx-Doc这样的程序转换为LaTex、man等更多格式。</p><p>本文语法来自<a href="https://link.jianshu.com?t=http://docutils.sourceforge.net/docs/user/rst/quickref.html"            target="_blank" rel="nofollow">Quick reStructuredText</a></p><p>由于格式原因，觉得这个不是很直观的话，可以到我的<a href="https://link.jianshu.com?t=https://github.com/SeayXu/CheatSheet" target="_blank"                              rel="nofollow">github</a>上查看。</p><h1>行内样式</h1><h2>斜体</h2><p>重点、解释文字</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-go"><code class="  language-go"><span class="token operator">*</span>重点<span            class="token punctuation">(</span>emphasis<span class="token punctuation">)</span>通常显示为斜体<span            class="token operator">*</span><span class="token string">`解释文字(interpreted text)通常显示为斜体`</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div><p><em>重点(emphasis)通常显示为斜体</em></p><h2>粗体</h2><p>重点强调</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-objectivec"><code class="  language-objectivec"><span            class="token operator">*</span><span            class="token operator">*</span>重点强调<span class="token punctuation">(</span>strong emphasis<span            class="token punctuation">)</span>通常显示为粗体<span class="token operator">*</span><span            class="token operator">*</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p><strong>重点强调(strong emphasis)通常显示为粗体</strong></p><h2>等宽</h2><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-go"><code class="  language-go"><span class="token string">``</span>行内文本<span            class="token punctuation">(</span>inline literal<span class="token punctuation">)</span>通常显示为等宽文本，空格可以保留，但是换行不可以。<span            class="token string">``</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>行内文本(inline literal)通常显示为等宽文本，空格可以保留，但是换行不可以。</p><h1>章节标题</h1><p>章节头部由下线(也可有上线)和包含标点的标题 组合创建, 其中下线要至少等于标准文本的长度。</p><p>可以表示标题的符号有    <strong>=</strong>、<strong>-</strong>、<strong>`</strong>、<strong>:</strong>、<strong>'</strong>、<strong>"</strong>、<strong>~</strong>、<strong>^</strong>、<strong>_</strong>    、<strong>*</strong> 、<strong>+</strong>、 <strong>#</strong>、<strong>&lt;</strong>、<strong>&gt;</strong> 。</p><p>对于相同的符号，有上标是一级标题，没有上标是二级标题。</p><p>标题最多分六级，可以自由组合使用。</p><p>全加上上标或者是全不加上标，使用不同的 6 个符号的标题依次排列，则会依次生成的标题为H1-H6。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-python"><code class="  language-python"><span            class="token operator">==</span><span class="token operator">==</span><span            class="token operator">==</span><span class="token operator">==</span><span            class="token operator">=</span>一级标题<span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span                class="token operator">==</span><span class="token operator">=</span>二级标题<span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span                class="token operator">==</span><span class="token operator">=</span><p>一级标题<br><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span                class="token operator">^</span><span class="token operator">^</span><span                class="token operator">^</span><span class="token operator">^</span><span                class="token operator">^</span><br>二级标题<br><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span                class="token operator">-</span><span class="token operator">-</span><span                class="token operator">-</span><span class="token operator">-</span><span                class="token operator">-</span><span class="token operator">-</span><br>三级标题<br><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;&gt;</span><span                class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span><br>四级标题<br><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span                class="token punctuation">:</span><span class="token punctuation">:</span><span                class="token punctuation">:</span><span class="token punctuation">:</span><span                class="token punctuation">:</span><span class="token punctuation">:</span><br>五级标题<br><span class="token triple-quoted-string string">‘’’’’’’</span><span class="token string">‘’</span><br>六级标题<br><span class="token triple-quoted-string string">“””””””</span>“<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><h1>一级标题</h1><h2>二级标题</h2><h1>一级标题</h1><h2>二级标题</h2><h3>三级标题</h3><h4>四级标题</h4><h5>五级标题</h5><h6>六级标题</h6><hr><h1>段落</h1><p>段落是被空行分割的文字片段，左侧必须对齐（没有空格，或者有相同多的空格）。</p><p>缩进的段落被视为引文。</p><h1>列表</h1><h2>符号列表(Bullet Lists)</h2><p>符号列表可以使用 <strong>-</strong>、 <strong>*</strong>、<strong>+</strong> 来表示。</p><p>不同的符号结尾需要加上空行，下级列表需要有空格缩进。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">- 符号列表1- 符号列表2<ul><li>二级符号列表1</li></ul><ul><li>二级符号列表2</li></ul><ul><li><p>二级符号列表3</p></li><li><p>符号列表3</p></li></ul><ul><li>符号列表4<br>&lt;span aria-hidden=”true”<pre><code>class=&quot;line-numbers-rows&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</code></pre></div><ul>  <li>符号列表1</li>  <li>符号列表2      <ul>          <li>二级符号列表1</li>      </ul>      <ul>          <li>二级符号列表2</li>      </ul>      <ul>          <li>二级符号列表3</li>      </ul>  </li></ul><ul>  <li>符号列表3</li></ul><ul>  <li>符号列表4</li></ul><h2>枚举(顺序)列表(Enumerated Lists)</h2><p>枚举列表算即顺序(序号)列表，可以使用不同的枚举序号来表示列表。</p><blockquote>  <p><strong>可以使用的枚举有：</strong></p></blockquote><ul>  <li>阿拉伯数字: 1, 2, 3, ... (无上限)。</li>  <li>大写字母: A-Z。</li>  <li>小写字母: a-z。</li>  <li>大写罗马数字: I, II, III, IV, ..., MMMMCMXCIX (4999)。</li>  <li>小写罗马数字: i, ii, iii, iv, ..., mmmmcmxcix (4999)。</li></ul><p>可以为序号添加前缀和后缀，下面的是被允许的。</p><p><strong>.</strong> 后缀: "1.", "A.", "a.", "I.", "i."。<br>  <strong>()</strong> 包起来: "(1)", "(A)", "(a)", "(I)", "(i)"。<br>  <strong>)</strong> 后缀: "1)", "A)", "a)", "I)", "i)"。</p><p>枚举列表可以结合 <strong>#</strong> 自动生成枚举序号。</p><div class="_2Uzcx_">  <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">      <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"           fill="currentColor" aria-hidden="true">          <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>      </svg>  </i></button>  <pre class="line-numbers  language-bash"><code class="  language-bash">1. 枚举列表1#. 枚举列表2#. 枚举列表3</li></ul><p>(I) 枚举列表1<br>(#) 枚举列表2<br>(#) 枚举列表3</p><p>A) 枚举列表1<br>#) 枚举列表2<br>#) 枚举列表3<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><ol>    <li>枚举列表1</li>    <li>枚举列表2</li>    <li>枚举列表3</li></ol><p>I. 枚举列表1<br>    II. 枚举列表2<br>    III. 枚举列表3</p><p>A. 枚举列表1<br>    B. 枚举列表2<br>    C. 枚举列表3</p><h2>定义列表(Definition Lists)</h2><p>定义列表可以理解为解释列表，即名词解释。</p><p>条目占一行，解释文本要有缩进；多层可根据缩进实现。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">定义1 这是定义1的内容<p>定义2<br> 这是定义2的内容<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>定义1</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">这是定义1的内容  <span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>定义2</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">这是定义2的内容<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><h2>字段列表(Field Lists)</h2><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">:标题: reStructuredText语法说明<p>:作者:</p><ul><li>Seay</li><li>Seay1</li><li>Seay2</li></ul><p>:时间: 2016年06月21日</p><p>:概述: 这是一篇<br> 关于reStructuredText</p><p> 语法说明。<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p><strong>标题:</strong> reStructuredText语法说明<br>    <strong>作者:</strong></p><ul>    <li>Seay</li>    <li>Seay1</li>    <li>Seay2</li></ul><p><strong>时间:</strong> 2016年06月21日<br>    <strong>概述:</strong> 这是一篇 关于reStructuredText<br>    语法说明。</p><h2>选项列表(Option Lists)</h2><p>选项列表是一个类似两列的表格，左边是参数，右边是描述信息。当参数选项过长时，参数选项和描述信息各占一行。</p><p>选项与参数之间有一个空格，参数选项与描述信息之间至少有两个空格。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-cpp"><code class="  language-cpp"><span class="token operator">-</span>a            command<span            class="token operator">-</span>line option <span class="token string">"a"</span><span class="token operator">-</span>b file       options can have arguments              <span class="token operator">and</span> <span class="token keyword">long</span> descriptions<span class="token operator">--</span><span class="token keyword">long</span>        options can be <span                class="token keyword">long</span> also<span class="token operator">--</span>input<span class="token operator">=</span>file  <span                class="token keyword">long</span> options can also have              arguments<span class="token operator">/</span>V            DOS<span class="token operator">/</span>VMS<span                class="token operator">-</span>style options too<span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div><table>    <thead>    <tr>        <th>参数选项</th>        <th>描述信息</th>    </tr>    </thead>    <tbody>    <tr>        <td>-a</td>        <td>command-line option "a"</td>    </tr>    <tr>        <td>-b file</td>        <td>options can have arguments and long descriptions</td>    </tr>    <tr>        <td>--long</td>        <td>options can be long also</td>    </tr>    <tr>        <td>--input=file</td>        <td>long options can also have arguments</td>    </tr>    <tr>        <td>/V</td>        <td>DOS/VMS-style options too</td>    </tr>    </tbody></table><p><em>由于格式问题，这里只是一个示例，实际上时没有上面的表头列和表格竖直线的。</em></p><h1>块(Blocks)</h1><h2>文字块(Literal Blocks)</h2><p>文字块就是一段文字信息，在需要插入文本块的段落后面加上 <strong>::</strong>，接着一个空行，然后就是文字块了。</p><p>文字块不能定顶头写，要有缩进，结束标志是，新的一段文本贴开头，即没有缩进。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">下面是文字块内容：::<p>   这是一段文字块<br>   同样也是文字块<br>   还是文字块</p><p>这是新的一段。<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>下面是文字块内容：</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">这是一段文字块同样也是文字块还是文字块<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div><p>这是新的一段。</p><h2>行块(Line Blocks)</h2><p>行块对于地址、诗句以及无装饰列表是非常有用的。行块是以 <strong>|</strong> 开头，每一个行块可以是多段文本。</p><p><strong>|</strong> 前后各有一个空格。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">下面是行块内容： <span class="token operator">|</span> 这是一段行块内容 <span class="token operator">|</span> 这同样也是行块内容   还是行块内容<p>这是新的一段。<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>下面是行块内容：</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">这是一段行块内容  这同样也是行块内容 还是行块内容<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div><p>这是新的一段。</p><h2>块引用(Block Quotes)</h2><p>块引用是通过缩进来实现的，引用块要在前面的段落基础上缩进。</p><p>通常引用结尾会加上出处(attribution)，出处的文字块开头是 <strong>--</strong>、<strong>---</strong> 、<strong>—</strong>，后面加上出处信息。</p><p>块引用可以使用空的注释 <strong>..</strong> 分隔上下的块引用。</p><p>注意在新的块和出处都要添加一个空行。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">下面是引用的内容：<pre><code>“真的猛士，敢于直面惨淡的人生，敢于正视淋漓的鲜血。”--- 鲁迅</code></pre><p>..</p><pre><code>  “人生的意志和劳动将创造奇迹般的奇迹。”  — 涅克拉索</code></pre><p><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>下面是引用的内容：</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">“真的猛士，敢于直面惨淡的人生，敢于正视淋漓的鲜血。”—鲁迅<p>“人生的意志和劳动将创造奇迹般的奇迹。”<br>—涅克拉索<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><h2>文档测试块(Doctest Blocks)</h2><p>文档测试块是交互式的Python会话，以 <strong>&gt;&gt;&gt;</strong> 开始，一个空行结束。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-python"><code class="  language-python"><span            class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span> <span class="token string">"This is a doctest block."</span>This <span class="token keyword">is</span> a doctest block<span class="token punctuation">.</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-python"><code class="  language-python"><span            class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span> <span class="token string">"This is a doctest block."</span>This <span class="token keyword">is</span> a doctest block<span class="token punctuation">.</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div><h1>表格(Tables)</h1><p>reStructuredText提供两种表格：网格表（Grid Tables），简单表（Simple Tables）。</p><h2>网格表(Grid Tables)</h2><p>网格表中使用的符号有：<strong>-</strong>、<strong>=</strong>、<strong>|</strong>、<strong>+</strong>。</p><p><strong>-</strong> 用来分隔行， <strong>=</strong> 用来分隔表头和表体行，<strong>|</strong> 用来分隔列，<strong>+</strong> 用来表示行和列相交的节点。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby"><span class="token constant">Grid</span> table<span            class="token punctuation">:</span><p><span class="token operator">+</span><span class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">+</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">+</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">-</span><span                class="token operator">+</span><br><span class="token operator">|</span> <span class="token constant">Header</span> <span                class="token number">1</span>   <span class="token operator">|</span> <span class="token constant">Header</span> <span                class="token number">2</span>   <span class="token operator">|</span> <span class="token constant">Header</span> <span                class="token number">3</span>  <span class="token operator">|</span><br><span class="token operator">+</span><span class="token operator">===</span><span class="token operator">===</span><span                class="token operator">===</span><span class="token operator">===</span><span                class="token operator">+</span><span class="token operator">===</span><span                class="token operator">===</span><span                class="token operator">===</span><span class="token operator">===</span><span                class="token operator">+</span><span class="token operator">===</span><span                class="token operator">===</span><span                class="token operator">===</span><span class="token operator">==</span><span                class="token operator">+</span><br><span class="token operator">|</span> body row <span class="token number">1</span> <span class="token operator">|</span> column <span                class="token number">2</span>   <span class="token operator">|</span> column <span                class="token number">3</span>  <span class="token operator">|</span><br><span class="token operator">+</span><span class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">+</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">+</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">-</span><span                class="token operator">+</span><br><span class="token operator">|</span> body row <span class="token number">2</span> <span class="token operator">|</span> <span                class="token constant">Cells</span> may span columns<span class="token punctuation">.</span><span                class="token operator">|</span><br><span class="token operator">+</span><span class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">+</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">+</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">-</span><span                class="token operator">+</span><br><span class="token operator">|</span> body row <span class="token number">3</span> <span class="token operator">|</span> <span                class="token constant">Cells</span> may  <span class="token operator">|</span> <span                class="token operator">-</span> <span class="token constant">Cells</span>   <span                class="token operator">|</span><br><span class="token operator">+</span><span class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">+</span> span rows<span                class="token punctuation">.</span> <span class="token operator">|</span> <span                class="token operator">-</span> contain <span class="token operator">|</span><br><span class="token operator">|</span> body row <span class="token number">4</span> <span class="token operator">|</span>            <span                class="token operator">|</span> <span class="token operator">-</span> blocks<span                class="token punctuation">.</span> <span class="token operator">|</span><br><span class="token operator">+</span><span class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">+</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">+</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span                class="token operator">–</span><span class="token operator">-</span><span                class="token operator">+</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>效果请查看:<a href="https://link.jianshu.com?t=http://docutils.sourceforge.net/docs/user/rst/quickref.html#tables"            target="_blank" rel="nofollow">这里</a></p><h2>简单表(Simple Tables)</h2><p>简单表相对于网格表，少了 <strong>|</strong> 和 <strong>+</strong> 两个符号，只用 <strong>-</strong> 和 <strong>=</strong> 表示。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-php"><code class="  language-php">Simple table<span            class="token punctuation">:</span><p><span class="token operator">===</span><span class="token operator">==</span>  <span                class="token operator">===</span><span class="token operator">==</span>  <span                class="token operator">===</span><span class="token operator">===</span><br>   Inputs     Output<br><span class="token operator">–</span><span class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span>  <span                class="token operator">–</span><span class="token operator">–</span><span                class="token operator">–</span><br>  <span class="token constant">A</span>      <span class="token constant">B</span>    <span                class="token constant">A</span> <span class="token keyword">or</span> <span                class="token constant">B</span><br><span class="token operator">===</span><span class="token operator">==</span>  <span                class="token operator">===</span><span class="token operator">==</span>  <span                class="token operator">===</span><span class="token operator">===</span><br><span class="token boolean constant">False</span>  <span class="token boolean constant">False</span>  <span                class="token boolean constant">False</span><br><span class="token boolean constant">True</span>   <span class="token boolean constant">False</span>  <span                class="token boolean constant">True</span><br><span class="token boolean constant">False</span>  <span class="token boolean constant">True</span>   <span                class="token boolean constant">True</span><br><span class="token boolean constant">True</span>   <span class="token boolean constant">True</span>   <span                class="token boolean constant">True</span><br><span class="token operator">===</span><span class="token operator">==</span>  <span                class="token operator">===</span><span class="token operator">==</span>  <span                class="token operator">===</span><span class="token operator">===</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>效果请查看:<a href="https://link.jianshu.com?t=http://docutils.sourceforge.net/docs/user/rst/quickref.html#tables"            target="_blank" rel="nofollow">这里</a></p><h1>分隔符</h1><p>分隔符就是一条水平的横线，是由 4 个 <strong>-</strong> 或者更多组成，需要添加换行。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">上面部分<hr><p>下面部分<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>上面部分</p><hr><p>下面部分</p><h1>超链接</h1><p>介绍各类带有链接性质的超链接</p><h2>自动超链接</h2><p>reStructuredText会自动将网址生成超链接。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-cpp"><code class="  language-cpp">https<span            class="token operator">:</span><span class="token operator">/</span><span            class="token operator">/</span>github<span class="token punctuation">.</span>com<span            class="token operator">/</span>SeayXu<span class="token operator">/</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p><a href="https://link.jianshu.com?t=https://github.com/SeayXu/" target="_blank" rel="nofollow">https://github.com/SeayXu/</a></p><h2>外部超链接(External Hyperlink)</h2><p>引用/参考(reference)，是简单的形式，只能是一个词语，引用的文字不能带有空格。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-cpp"><code class="  language-cpp">这篇文章来自我的Github<span            class="token punctuation">,</span>请参考 reference_。<p><span class="token punctuation">.</span><span class="token punctuation">.</span> _reference<span class="token operator">:</span> https<span                class="token operator">:</span><span class="token operator">/</span><span                class="token operator">/</span>github<span class="token punctuation">.</span>com<span                class="token operator">/</span>SeayXu<span class="token operator">/</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></p></div><p>引用/参考(reference)，行内形式，引用的文字可以带有空格或者符号。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-cpp"><code class="  language-cpp">这篇文章来自我的Github<span            class="token punctuation">,</span>请参考 `SeayXu <span class="token operator">&lt;</span>https<span            class="token operator">:</span><span class="token operator">/</span><span            class="token operator">/</span>github<span class="token punctuation">.</span>com<span            class="token operator">/</span>SeayXu<span class="token operator">/</span><span            class="token operator">&gt;</span>`_。<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>这篇文章来自我的Github,请参考 <a href="https://link.jianshu.com?t=https://github.com/SeayXu/" target="_blank"                         rel="nofollow">SeayXu</a>。</p><h2>内部超链接|锚点(Internal Hyperlink)</h2><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">更多信息参考 引用文档_<p>这里是其他内容</p><p>.. _引用文档:</p><p>这是引用部分的内容<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>更多信息参考 <a href="#id1" target="_blank">引用文档</a></p><p>这里是其他内容</p><p>&lt;h6 id="id1"&gt;&lt;/h6&gt;</p><p>这是引用部分的内容</p><h2>匿名超链接(Anonymous hyperlink)</h2><p>词组(短语)引用/参考(phrase reference)，引用的文字可以带有空格或者符号，需要使用反引号引起来。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-go"><code class="  language-go">这篇文章参考的是：<span class="token string">`Quick reStructuredText`</span>__。<p><span class="token punctuation">.</span><span class="token punctuation">.</span> __<span                class="token punctuation">:</span> http<span class="token punctuation">:</span><span                class="token operator">/</span><span class="token operator">/</span>docutils<span                class="token punctuation">.</span>sourceforge<span class="token punctuation">.</span>net<span                class="token operator">/</span>docs<span class="token operator">/</span>user<span                class="token operator">/</span>rst<span class="token operator">/</span>quickref<span                class="token punctuation">.</span>html<br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></p></div><p>这篇文章来自我的Github,请参考 <a        href="https://link.jianshu.com?t=http://docutils.sourceforge.net/docs/user/rst/quickref.html"        target="_blank" rel="nofollow">Quick reStructuredText</a>。</p><h2>间接超链接(Indirect Hyperlink)</h2><p>间接超链接是基于匿名链接的基础上的，就是将匿名链接地址换成了外部引用名_。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-go"><code class="  language-go">SeayXu_ 是 <span class="token string">`我的 GitHub 用户名`</span>__。<p><span class="token punctuation">.</span><span class="token punctuation">.</span> _SeayXu<span class="token punctuation">:</span> https<span                class="token punctuation">:</span><span class="token operator">/</span><span                class="token operator">/</span>github<span                class="token punctuation">.</span>com<span class="token operator">/</span>SeayXu<span                class="token operator">/</span></p><p>__ SeayXu_<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p><a href="https://link.jianshu.com?t=https://github.com/SeayXu/" target="_blank" rel="nofollow">SeayXu</a> 是 <a        href="https://link.jianshu.com?t=https://github.com/SeayXu/" target="_blank" rel="nofollow">我的 GitHub    用户名</a>。</p><h2>隐式超链接(Implicit Hyperlink)</h2><p>小节标题、脚注和引用参考会自动生成超链接地址，使用小节标题、脚注或引用参考名称作为超链接名称就可以生成隐式链接。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-go"><code class="  language-go">第一节 介绍<span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span                class="token operator">==</span><span class="token operator">==</span><span                class="token operator">=</span><p>其他内容<span class="token operator">…</span></p><p>隐式链接到 <span class="token string"><code>第一节 介绍</code></span><span class="token boolean">_</span>，即可生成超链接。<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>&lt;h6 id="id2"&gt;第一节 介绍&lt;/h6&gt;</p><p>其他内容...</p><p>隐式链接到 <a href="#id2" target="_blank">第一节 介绍</a>，即可生成超链接。</p><h2>替换引用(Substitution Reference)</h2><p>替换引用就是用定义的指令替换对应的文字或图片，和内置指令(inline directives)类似。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-cpp"><code class="  language-cpp">这是 <span            class="token operator">|</span>logo<span            class="token operator">|</span> github的Logo，我的github用户名是<span class="token operator">:</span><span            class="token operator">|</span>name<span class="token operator">|</span>。<p><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token operator">|</span>logo<span                class="token operator">|</span> image<span class="token operator">::</span> https<span                class="token operator">:</span><span class="token operator">/</span><span                class="token operator">/</span>help<span class="token punctuation">.</span>github<span                class="token punctuation">.</span>com<span class="token operator">/</span>assets<span                class="token operator">/</span>images<span class="token operator">/</span>site<span                class="token operator">/</span>favicon<span class="token punctuation">.</span>ico<br><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token operator">|</span>name<span                class="token operator">|</span> replace<span class="token operator">::</span> SeayXu<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></p></div><p></p><p></p>这是<div class="image-package">    <img src= "/img/loading.gif" data-lazy-src="https://help.github.com/assets/images/site/favicon.ico"         data-original-src="https://help.github.com/assets/images/site/favicon.ico" data-image-index="1"         style="cursor: zoom-in;">    <div class="image-caption"></div></div><p> GitHub的Logo，我的github用户名是:SeayXu。</p><h2>脚注引用(Footnote Reference)</h2><p>脚注引用，有这几个方式：有手工序号(标记序号123之类)、自动序号(填入#号会自动填充序号)、自动符号(填入*会自动生成符号)。</p><p>手工序号可以和#结合使用，会自动延续手工的序号。</p><p><strong>#</strong> 表示的方法可以在后面加上一个名称，这个名称就会生成一个链接。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-css"><code class="  language-css">脚注引用一 [1]_脚注引用二 [#]_脚注引用三 [#链接]_脚注引用四 [*]_脚注引用五 [*]_脚注引用六 [*]_<p>.. [1] 脚注内容一<br>.. [2] 脚注内容二<br>.. [#] 脚注内容三<br>.. [#链接] 脚注内容四 链接_<br>.. [<em>] 脚注内容五<br>.. [</em>] 脚注内容六<br>.. [*] 脚注内容七<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>脚注引用一 <a href="#id3" target="_blank">[1]</a>&lt;a id="id9"&gt;&lt;/a&gt;<br>    脚注引用二 <a href="#id4" target="_blank">[3]</a>&lt;a id="id10"&gt;&lt;/a&gt;<br>    脚注引用三 <a href="#id5" target="_blank">[4]</a>&lt;a id="id11"&gt;&lt;/a&gt;<br>    脚注引用四 <a href="#id6" target="_blank">[*]</a>&lt;a id="id12"&gt;&lt;/a&gt;<br>    脚注引用五 <a href="#id7" target="_blank">[†]</a>&lt;a id="id13"&gt;&lt;/a&gt;<br>    脚注引用六 <a href="#id8" target="_blank">[‡]</a>&lt;a id="id14"&gt;&lt;/a&gt;</p><p><a href="#id9" target="_blank">[1]</a>&lt;a id="id3"&gt;&lt;/a&gt; 脚注内容一<br>    [2] 脚注内容二<br>    <a href="#id10" target="_blank">[3]</a>&lt;a id="id4"&gt;&lt;/a&gt; 脚注内容三<br>    <a href="#id11" target="_blank">[4]</a>&lt;a id="id5"&gt;&lt;/a&gt; 脚注内容四 <a href="#id11" target="_blank">链接</a>    <br>    <a href="#id12" target="_blank">[*]</a>&lt;a id="id6"&gt;&lt;/a&gt; 脚注内容五<br>    <a href="#id13" target="_blank">[†]</a>&lt;a id="id7"&gt;&lt;/a&gt; 脚注内容六<br>    <a href="#id14" target="_blank">[‡]</a>&lt;a id="id8"&gt;&lt;/a&gt; 脚注内容七</p><h2>引用参考(Citation Reference)</h2><p>引用参考与上面的脚注有点类似。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-css"><code class="  language-css">引用参考的内容通常放在页面结尾处，比如 [One]_，Two_<p>.. [One] 参考引用一<br>.. [Two] 参考引用二<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>引用参考的内容通常放在页面结尾处，比如 <a href="#15" target="_blank">[One]</a>&lt;a id="id17"&gt;&lt;/a&gt;，<a href="#16"                                                                                               target="_blank">Two</a></p><blockquote>    <p><a href="#17" target="_blank">[One]</a>&lt;a id="id15"&gt;&lt;/a&gt; 参考引用一<br>        [Two]&lt;a id="id16"&gt;&lt;/a&gt; 参考引用二</p></blockquote><h1>注释(Comments)</h1><p>注释以 <strong>..</strong> 开头，后面接注释内容即可，可以是多行内容，多行时每行开头要加一个空格。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">.. 我是注释内容 你们看不到我<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div><p>关于 <a        href="https://link.jianshu.com?t=https://github.com/SeayXu/CheatSheet/blob/master/files/reStructuredText-Directives-Syntax.md"        target="_blank" rel="nofollow">指令(Directives)</a>，在下一篇中专门做语法说明。</p><p>如果有不正确的地方，希望你能指出。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tornado学习笔记day03</title>
      <link href="python/tornado/tornado-note3/"/>
      <url>python/tornado/tornado-note3/</url>
      
        <content type="html"><![CDATA[<h1 id="write"><a href="#write" class="headerlink" title="write:"></a>write:</h1><h3 id="作用"><a href="#作用" class="headerlink" title="作用:"></a>作用:</h3><p>将chunk中的数据写到输出缓冲区</p><h3 id="利用write方法写json数据"><a href="#利用write方法写json数据" class="headerlink" title="利用write方法写json数据"></a>利用write方法写json数据</h3><ul><li>我们自己手动序列化json的那种方式Content-Type 的属性值为text-html</li><li>而我们采用write自动序列化方式,我们的content-type 属性为application/json</li></ul><h1 id="set-default-headers"><a href="#set-default-headers" class="headerlink" title="set_default_headers():"></a>set_default_headers():</h1><h3 id="作用-1"><a href="#作用-1" class="headerlink" title="作用:"></a>作用:</h3><ul><li>在进入HTTP响应方法之前被调用</li><li>可以重新写该方法来设置默认的headers<h3 id="注意"><a href="#注意" class="headerlink" title="注意:"></a>注意:</h3></li><li>在这个HTTP处理方法中使用set_header设置的字段会覆盖set_default_headers()的值</li><li>这个set_header和set_default_headers()是有执行的先后顺序的,默认那个当然那先就执行了<h1 id="set-status-status-code-reason-none"><a href="#set-status-status-code-reason-none" class="headerlink" title="set_status(status_code,reason=none):"></a>set_status(status_code,reason=none):</h1><h3 id="作用-为响应设置状态码"><a href="#作用-为响应设置状态码" class="headerlink" title="作用:为响应设置状态码"></a>作用:为响应设置状态码</h3><h3 id="参数"><a href="#参数" class="headerlink" title="参数:"></a>参数:</h3><h4 id="status-code"><a href="#status-code" class="headerlink" title="status_code:"></a>status_code:</h4></li><li>状态码的值,为int类型</li><li>如果reason的值为none,则状态码必须为正常值<h4 id="reason"><a href="#reason" class="headerlink" title="reason"></a>reason</h4></li><li>String类型</li><li>描述状态码的词组,比如<code>404 not found</code> 中的<code>not found</code> </li></ul><h1 id="重定向-self-redirect-url"><a href="#重定向-self-redirect-url" class="headerlink" title="重定向 self.redirect(url):"></a>重定向 <code>self.redirect(url)</code>:</h1><h4 id="作用-2"><a href="#作用-2" class="headerlink" title="作用:"></a>作用:</h4><ul><li>比如你有时候写index,有时候不写,都能进到首页里面,这就是重定向的作用</li><li>重定向到url网址<h4 id="示例"><a href="#示例" class="headerlink" title="示例:"></a>示例:</h4></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RedirectHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 直接就重定向了</span></span><br><span class="line">        self.redirect(<span class="string">&quot;/&quot;</span>)</span><br></pre></td></tr></table></figure><h1 id="self-send-error-status-code-500-kwargs"><a href="#self-send-error-status-code-500-kwargs" class="headerlink" title="self.send_error(status_code = 500,**kwargs):"></a><code>self.send_error(status_code = 500,**kwargs)</code>:</h1><ul><li>作用:<ul><li>抛出HTTP错误状态码,默认为500</li><li>tornado会调用write_error()方法进行处理</li><li>对应Django里面自定义404一样<h1 id="write-error-status-code-kwargs"><a href="#write-error-status-code-kwargs" class="headerlink" title="write_error(status_code,**kwargs):"></a><code>write_error(status_code,**kwargs)</code>:</h1></li></ul></li><li>作用:<ul><li>用来处理send_error抛出的错误信息,并返回给浏览器错误界面</li></ul></li><li>示例:<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ErrorHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">write_error</span>(<span class="params">self, status_code: <span class="built_in">int</span>, **kwargs: Any</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        <span class="keyword">if</span> status_code == <span class="number">500</span>:</span><br><span class="line">            self.write(<span class="string">&quot;服务器内部错误500了&quot;</span>)</span><br><span class="line">        <span class="keyword">elif</span> status_code == <span class="number">404</span>:</span><br><span class="line">            self.write(<span class="string">&quot;资源不存在&quot;</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.write(<span class="string">&quot;我也不知道是啥错误&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 直接就重定向了</span></span><br><span class="line">        flag = self.get_query_argument(<span class="string">&quot;flag&quot;</span>)</span><br><span class="line">        <span class="keyword">if</span> flag == <span class="string">&#x27;0&#x27;</span>:</span><br><span class="line">            print(<span class="string">&quot;有错误&quot;</span>)</span><br><span class="line">            self.send_error(<span class="number">500</span>)</span><br><span class="line">            <span class="comment"># 这里抛出错误,下面就不会执行了</span></span><br><span class="line"></span><br><span class="line">        print(<span class="string">&quot;没毛病&quot;</span>)</span><br><span class="line"></span><br><span class="line">        self.write(<span class="string">&quot;you are right!&quot;</span>)</span><br><span class="line">```    </span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"><span class="comment"># 路由的反向解析</span></span><br><span class="line">这个tornado里面的比Django的反向解析还要简单一点 </span><br><span class="line"></span><br><span class="line">给路由起个名字,便于url改变后,跳转链接失效</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">### 应用端</span></span><br><span class="line">```python</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Application</span>(<span class="params">tornado.web.Application</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        handlers = [</span><br><span class="line">            (<span class="string">r&quot;/&quot;</span>, index.IndexHandler),</span><br><span class="line">            (<span class="string">r&quot;/sunck&quot;</span>, index.SunckHandler,&#123;<span class="string">&#x27;name&#x27;</span>:<span class="string">&quot;victor&quot;</span>,<span class="string">&#x27;age&#x27;</span>:<span class="number">19</span>&#125;),</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">            <span class="comment"># 状态码</span></span><br><span class="line">            (<span class="string">r&quot;/status&quot;</span>, index.StatusHandler),</span><br><span class="line">            <span class="comment"># 重定向</span></span><br><span class="line">            (<span class="string">r&quot;/index&quot;</span>, index.RedirectHandler),</span><br><span class="line">            <span class="comment"># 错误处理</span></span><br><span class="line">            <span class="comment"># iserror?flag=2</span></span><br><span class="line">            <span class="comment"># 如果等于0就说明,有错误,不等于0就说明没有错误</span></span><br><span class="line">            (<span class="string">r&quot;/iserror&quot;</span>, index.ErrorHandler),</span><br><span class="line"></span><br><span class="line">            tornado.web.url(<span class="string">r&quot;/kaige&quot;</span>,index.KaigeHandler,name=<span class="string">&#x27;kaige&#x27;</span>),</span><br><span class="line">        ]</span><br><span class="line">        <span class="built_in">super</span>(Application,self).__init__(handlers)</span><br></pre></td></tr></table></figure></li></ul><h3 id="视图函数"><a href="#视图函数" class="headerlink" title="视图函数"></a>视图函数</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;&lt;br&gt;&quot;</span>)</span><br><span class="line">        url = self.reverse_url(<span class="string">&quot;kaige&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;&lt;a href=&#x27;%s&#x27;&gt;去另一个页面&lt;/a&gt;&quot;</span> % (url))</span><br><span class="line">        <span class="comment"># self.write(&quot;&lt;a href=&quot;+url+&quot;&gt;去另一个页面&lt;/a&gt;&quot;)</span></span><br></pre></td></tr></table></figure><h1 id="tornado-Web-RequestHandler"><a href="#tornado-Web-RequestHandler" class="headerlink" title="tornado.Web.RequestHandler"></a>tornado.Web.RequestHandler</h1><h3 id="利用HTTP协议向服务器传递参数"><a href="#利用HTTP协议向服务器传递参数" class="headerlink" title="利用HTTP协议向服务器传递参数"></a>利用HTTP协议向服务器传递参数</h3><h3 id="提取uri的特定部分"><a href="#提取uri的特定部分" class="headerlink" title="提取uri的特定部分"></a>提取uri的特定部分</h3><p><code>http://127.0.0.1:8080/good/nice/handsome/cool</code></p><p>实例代码,app部分</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27; (r&quot;/good/(\w+)/(\w+)/(\w+)&quot;, index.GoodHandler),&#x27;&#x27;&#x27;</span></span><br><span class="line">(<span class="string">r&quot;/good/(?P&lt;p1&gt;\w+)/(?P&lt;p3&gt;\w+)/(?P&lt;p2&gt;\w+)&quot;</span>, index.GoodHandler),</span><br></pre></td></tr></table></figure><p>视图函数部分</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GoodHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self,p1,p3,p2</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;GoodHandler kaige !&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;&lt;br&gt;&quot;</span>)</span><br><span class="line">        self.write(p3)</span><br><span class="line">        self.write(<span class="string">&quot;&lt;br&gt;&quot;</span>)</span><br><span class="line">        self.write(p2)</span><br><span class="line">        self.write(<span class="string">&quot;&lt;br&gt;&quot;</span>)</span><br><span class="line">        self.write(p1)                  </span><br></pre></td></tr></table></figure><h3 id="查询字符串-GET方式传递参数"><a href="#查询字符串-GET方式传递参数" class="headerlink" title="查询字符串(GET方式传递参数)"></a>查询字符串(GET方式传递参数)</h3><h4 id="http-127-0-0-1-8080-zhangmanyu-a-1-amp-b-2-amp-c-4类型"><a href="#http-127-0-0-1-8080-zhangmanyu-a-1-amp-b-2-amp-c-4类型" class="headerlink" title="http://127.0.0.1:8080/zhangmanyu?a=1&amp;b=2&amp;c=4类型"></a><code>http://127.0.0.1:8080/zhangmanyu?a=1&amp;b=2&amp;c=4</code>类型</h4><h5 id="这里有一个方法"><a href="#这里有一个方法" class="headerlink" title="这里有一个方法"></a>这里有一个方法</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_query_argument</span>(<span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        self,</span></span></span><br><span class="line"><span class="function"><span class="params">        name: <span class="built_in">str</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">        default: Union[<span class="literal">None</span>, <span class="built_in">str</span>, _ArgDefaultMarker] = _ARG_DEFAULT,</span></span></span><br><span class="line"><span class="function"><span class="params">        strip: <span class="built_in">bool</span> = <span class="literal">True</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    </span>) -&gt; Optional[str]:</span></span><br></pre></td></tr></table></figure><h5 id="参数-1"><a href="#参数-1" class="headerlink" title="参数"></a>参数</h5><h6 id="name"><a href="#name" class="headerlink" title="name:"></a>name:</h6><ul><li>从get请求参数中返回指定参数的值</li><li>如果出现同名参数,理论上这个方法会返回最后一个值<h6 id="default"><a href="#default" class="headerlink" title="default"></a>default</h6></li><li>如果我们设置了为未传递name参数,它会返回默认的值<h6 id="strip"><a href="#strip" class="headerlink" title="strip"></a>strip</h6></li><li>表示是否过滤掉两边的空白字符</li><li>默认为True,过滤<h4 id="http-127-0-0-1-8080-zhangmanyu-a-1-amp-a-2-amp-c-4类型"><a href="#http-127-0-0-1-8080-zhangmanyu-a-1-amp-a-2-amp-c-4类型" class="headerlink" title="http://127.0.0.1:8080/zhangmanyu?a=1&amp;a=2&amp;c=4类型"></a><code>http://127.0.0.1:8080/zhangmanyu?a=1&amp;a=2&amp;c=4</code>类型</h4></li><li>一般情况下,很少出现这种情况的</li><li><code>def get_query_arguments(self, name: str, strip: bool = True) -&gt; List[str]:</code></li><li>参数: 同上<h3 id="请求体携带数据-POST方式传递参数"><a href="#请求体携带数据-POST方式传递参数" class="headerlink" title="请求体携带数据(POST方式传递参数)"></a>请求体携带数据(POST方式传递参数)</h3></li><li>这个厉害了,比Django方便,不用在定义一路由函数了,直接在类里面加一个方法就就行了</li><li>原型在这里<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_body_argument</span>(<span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        self,</span></span></span><br><span class="line"><span class="function"><span class="params">        name: <span class="built_in">str</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">        default: Union[<span class="literal">None</span>, <span class="built_in">str</span>, _ArgDefaultMarker] = _ARG_DEFAULT,</span></span></span><br><span class="line"><span class="function"><span class="params">        strip: <span class="built_in">bool</span> = <span class="literal">True</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    </span>) -&gt; Optional[str]:</span></span><br></pre></td></tr></table></figure><h3 id="既可以获取GET请求-也可以获取POST请求"><a href="#既可以获取GET请求-也可以获取POST请求" class="headerlink" title="既可以获取GET请求,也可以获取POST请求"></a>既可以获取GET请求,也可以获取POST请求</h3></li><li>直接就上原型就OK了,你不仅要学会举一反三,还要自己进行拓展</li><li>原型在这里<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_argument</span>(<span class="params">  <span class="comment"># noqa: F811</span></span></span></span><br><span class="line"><span class="function"><span class="params">    self,</span></span></span><br><span class="line"><span class="function"><span class="params">    name: <span class="built_in">str</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    default: Union[<span class="literal">None</span>, <span class="built_in">str</span>, _ArgDefaultMarker] = _ARG_DEFAULT,</span></span></span><br><span class="line"><span class="function"><span class="params">    strip: <span class="built_in">bool</span> = <span class="literal">True</span>,</span></span></span><br><span class="line"><span class="function"><span class="params"></span>) -&gt; Optional[str]:</span></span><br></pre></td></tr></table></figure></li><li><strong>其实有时候,有的结构,看源码才能理解的更加的深刻</strong></li><li>还有一个多个的,也是这么回事儿<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_arguments</span>(<span class="params">self, name: <span class="built_in">str</span>, strip: <span class="built_in">bool</span> = <span class="literal">True</span></span>) -&gt; List[str]:</span></span><br></pre></td></tr></table></figure><h3 id="在HTTP报文头中-增加自定义的字段"><a href="#在HTTP报文头中-增加自定义的字段" class="headerlink" title="在HTTP报文头中,增加自定义的字段"></a>在HTTP报文头中,增加自定义的字段</h3></li></ul><h1 id="request对象"><a href="#request对象" class="headerlink" title="request对象"></a>request对象</h1><h3 id="作用-3"><a href="#作用-3" class="headerlink" title="作用"></a>作用</h3><ul><li>存储了关于请求的相关信息<h3 id="比如"><a href="#比如" class="headerlink" title="比如:"></a>比如:</h3></li><li><code>HTTPServerRequest(protocol=&#39;http&#39;, host=&#39;127.0.0.1:8080&#39;, method=&#39;GET&#39;, uri=&#39;/zhuyin&#39;, version=&#39;HTTP/1.1&#39;, remote_ip=&#39;127.0.0.1&#39;)</code>    <h3 id="属性"><a href="#属性" class="headerlink" title="属性"></a>属性</h3></li><li>method: HTTP请求的方式</li><li>host: 被请求的主机名(服务器的主机名) </li><li>uri: 请求的完整资源地址,包括路径和get查询的参数部分 </li><li>path: 请求的路径部分</li><li>query: 请求参数部分 </li><li>version: 使用的HTTP版本 </li><li>headers: 请求的协议头,字典类型 </li><li>body: 请求体数据(POST) </li><li>remote_ip: 客户端的ip地址 </li><li>files: 用户上传的文件,字典类型 </li></ul><h1 id="tornado-httputil-HTTPFile对象"><a href="#tornado-httputil-HTTPFile对象" class="headerlink" title="tornado.httputil.HTTPFile对象"></a>tornado.httputil.HTTPFile对象</h1><ul><li>功能:在我们上传文件中才能看到他</li><li>作用:<br>  是收到的文件对象<h3 id="属性-1"><a href="#属性-1" class="headerlink" title="属性:"></a>属性:</h3></li><li>filename: 文件的实际名字</li><li>body: 文件的数据实体</li><li>content-type: 上传文件的类型<h3 id="文件上传"><a href="#文件上传" class="headerlink" title="文件上传"></a>文件上传</h3></li></ul><p>首先,先要滤清一个数据结构,就是request.file对象的数据结构</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">一个request.file对象的结构示例</span></span><br><span class="line"><span class="string">&#123;</span></span><br><span class="line"><span class="string">    &#x27;file&#x27;: [</span></span><br><span class="line"><span class="string">        &#123;&#x27;filename&#x27;: &#x27;a.txt&#x27;,</span></span><br><span class="line"><span class="string">         &#x27;body&#x27;: b&#x27;suck is a wonderful man&#x27;,</span></span><br><span class="line"><span class="string">          &#x27;content_type&#x27;: &#x27;text/plain&#x27;</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        &#123;&#x27;filename&#x27;: &#x27;reg.md&#x27;,</span></span><br><span class="line"><span class="string">          &#x27;body&#x27;: b&#x27;x9xa0&#x27;,</span></span><br><span class="line"><span class="string">           &#x27;content_type&#x27;: &#x27;application/octet-stream&#x27;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">    ]</span></span><br><span class="line"><span class="string">    </span></span><br><span class="line"><span class="string">    &#x27;img&#x27;: [</span></span><br><span class="line"><span class="string">        &#123;&#x27;filename&#x27;: &#x27;a.img&#x27;,</span></span><br><span class="line"><span class="string">         &#x27;body&#x27;: b&#x27;as\dfhg\ahhf\a\\h\ahfh\af&#x27;,</span></span><br><span class="line"><span class="string">          &#x27;content_type&#x27;: &#x27;text/plain&#x27;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">    ]</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>然后,用循环来进行遍历!</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UpFileHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.render(<span class="string">&quot;upfile.html&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">post</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;上传成功!&quot;</span>)</span><br><span class="line">        contents = self.request.files</span><br><span class="line">        <span class="keyword">for</span> content <span class="keyword">in</span> contents:</span><br><span class="line">            fileArr = contents[content]</span><br><span class="line">            <span class="keyword">for</span> fileObj <span class="keyword">in</span> fileArr:</span><br><span class="line">                file_path = os.path.join(BASE_DIR,<span class="string">&quot;upfile/&quot;</span>+fileObj.filename)</span><br><span class="line">                <span class="keyword">with</span> <span class="built_in">open</span>(file_path,<span class="string">&quot;wb&quot;</span>) <span class="keyword">as</span> f:</span><br><span class="line">                    f.write(fileObj.body)</span><br><span class="line">                print(<span class="string">&quot;文件写入成功&quot;</span>)</span><br></pre></td></tr></table></figure><p>我知道,要是看不懂那就加一点批注呗!</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27; 导入系统操作模块,用于存储接受的文件&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="comment"># 导入BASE_DIR,定位到服务器中的绝对路径</span></span><br><span class="line"><span class="keyword">from</span> config <span class="keyword">import</span> BASE_DIR</span><br><span class="line"><span class="keyword">from</span> tornado.web <span class="keyword">import</span> RequestHandler</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UpFileHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    用于上传文件的视图类,其中包含显示表单的get方法</span></span><br><span class="line"><span class="string">    和用于处理上传的POST方法</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    <span class="comment"># get方法,加载表单模板</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.render(<span class="string">&quot;upfile.html&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 文件上传指定是POST请求啦</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">post</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 用于接收上传的信息</span></span><br><span class="line">        self.write(<span class="string">&quot;上传成功!&quot;</span>)</span><br><span class="line">        <span class="comment"># 通过request.files对象来获取所有文件对象内容</span></span><br><span class="line">        contents = self.request.files</span><br><span class="line">        <span class="comment"># 遍历最大的字典,拿到没个name类型的字典的键</span></span><br><span class="line">        <span class="comment"># 其中content是字典中的键,比如file,img</span></span><br><span class="line">        <span class="keyword">for</span> content <span class="keyword">in</span> contents:</span><br><span class="line">            <span class="comment"># 通过键获取值,拿到相同name的文件列表</span></span><br><span class="line">            <span class="comment"># 这个filearr,就是一个list</span></span><br><span class="line">            fileArr = contents[content]</span><br><span class="line">            <span class="comment"># 遍历文件列表</span></span><br><span class="line">            <span class="comment"># 这个fileObj又是一个dict字典类型</span></span><br><span class="line">            <span class="keyword">for</span> fileObj <span class="keyword">in</span> fileArr:</span><br><span class="line">                <span class="comment"># 定义存储路径</span></span><br><span class="line">                <span class="comment"># 通过BASE_DIR来获取服务器的绝对位置</span></span><br><span class="line">                <span class="comment"># 其中通过这个fileObj的字典的filename键,</span></span><br><span class="line">                <span class="comment"># 来获取文件名字,来定义存储路径的文件名称</span></span><br><span class="line">                file_path = os.path.join(BASE_DIR,<span class="string">&quot;upfile/&quot;</span>+fileObj.filename)</span><br><span class="line">                <span class="comment"># 写入文件</span></span><br><span class="line">                <span class="keyword">with</span> <span class="built_in">open</span>(file_path,<span class="string">&quot;wb&quot;</span>) <span class="keyword">as</span> f:</span><br><span class="line">                    <span class="comment"># 文件的内容就是body</span></span><br><span class="line">                    f.write(fileObj.body)</span><br><span class="line">                    <span class="comment"># TODO 这里还需要处理的就是,用户上传同名文件</span></span><br><span class="line">                    <span class="comment">#  导致文件重新在服务器中覆盖的问题</span></span><br><span class="line">                print(<span class="string">&quot;文件写入成功&quot;</span>)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> tornado </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tornado学习笔记day04</title>
      <link href="python/tornado/tornado-note4/"/>
      <url>python/tornado/tornado-note4/</url>
      
        <content type="html"><![CDATA[<h1 id="响应输出-gt-write"><a href="#响应输出-gt-write" class="headerlink" title="响应输出 -&gt; write"></a>响应输出 -&gt; write</h1><h3 id="原型"><a href="#原型" class="headerlink" title="原型"></a>原型</h3><h4 id="self-write-函数"><a href="#self-write-函数" class="headerlink" title="self.write()函数"></a>self.write()函数</h4><p>源码中是这样定义的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">write</span>(<span class="params">self, chunk: Union[<span class="built_in">str</span>, <span class="built_in">bytes</span>, <span class="built_in">dict</span>]</span>) -&gt; <span class="keyword">None</span>:</span></span><br></pre></td></tr></table></figure><h3 id="作用"><a href="#作用" class="headerlink" title="作用"></a>作用</h3><p>将chunk数据写到缓冲区</p><h3 id="刷新缓冲区的四种方式"><a href="#刷新缓冲区的四种方式" class="headerlink" title="刷新缓冲区的四种方式"></a>刷新缓冲区的四种方式</h3><ul><li>程序中断</li><li>手动刷新</li><li>缓冲区满了</li><li>遇到\n</li></ul><p>当你写了一个print之后,不是直接就显示在黑屏中断上面的,而是先到缓冲区走一个趟</p><p>只是我们python演示不了,这个得用C语言来演示,还得是Linux系统才行,两种条件都不具备</p><h3 id="C程序演示"><a href="#C程序演示" class="headerlink" title="C程序演示"></a>C程序演示</h3><p>这里我们需要gcc或者g++(编译C++的)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># include&lt;stdio.h&gt;</span></span><br><span class="line"><span class="built_in">int</span> main()&#123;</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</span><br><span class="line">        printf(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">        sleep(<span class="number">0.05</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="基础"><a href="#基础" class="headerlink" title="基础"></a>基础</h3><p>代码演示</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">WriteHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;write page info tornado!&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;write page nicie tornado!&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;write page coll tornado!&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;write page beautiful tornado!&quot;</span>)</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        你会发现他们是连着的,因为我都写在了缓冲区里面</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 刷新缓冲区, 并关闭当前请求通道</span></span><br><span class="line">        self.finish()</span><br><span class="line">        <span class="comment"># 如果我不写他,当我们的程序结束,他也会刷新了</span></span><br><span class="line">        <span class="comment"># 下面这行就写丢了</span></span><br><span class="line">        self.write(<span class="string">&quot;write page wonderful tornado!&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="利用write方法写JSON数据"><a href="#利用write方法写JSON数据" class="headerlink" title="利用write方法写JSON数据"></a>利用write方法写JSON数据</h3><p>在Django那时候是不是有JsonResponse<br>比如在豆瓣影评<br>当我们往下滚轮的时候请求JSON数据<br>在本地通过创建DOM的方式进行加载的</p><h1 id="接口调用顺序"><a href="#接口调用顺序" class="headerlink" title="接口调用顺序"></a>接口调用顺序</h1><h2 id="方法"><a href="#方法" class="headerlink" title="方法"></a>方法</h2><h3 id="initialize"><a href="#initialize" class="headerlink" title="initialize()"></a>initialize()</h3><h3 id="prepare"><a href="#prepare" class="headerlink" title="prepare()"></a>prepare()</h3><ul><li>作用: 预处理方法,在执行对应的请求方法之前调用</li><li>注意: <ul><li>任何一种HTTP请求,都会执行prepare()方法</li><li>这个prepare有点想Django里面的中间件,但是中间件能够在之前或者之后来执行</li><li>这个只是在HTTP方法之前执行</li><li>能够用于一些,比如反爬虫,我要是不想让你正常请求,不给你响应内容,那我这里直接来个error直接跳过write就OK了</li><li>判断用户是否符合规格<h3 id="HTTP方法"><a href="#HTTP方法" class="headerlink" title="HTTP方法"></a>HTTP方法</h3></li></ul></li></ul><h4 id="get-参数在URL后面"><a href="#get-参数在URL后面" class="headerlink" title="get(参数在URL后面)"></a>get(参数在URL后面)</h4><ul><li>优点:速度快</li><li>缺点:承载的数据量低,安全性相对低</li></ul><h4 id="post-参数单独打包"><a href="#post-参数单独打包" class="headerlink" title="post(参数单独打包)"></a>post(参数单独打包)</h4><ul><li>优点:速度慢</li><li>缺点:承载的数据量高,安全性相对高了那么一丢丢</li><li>一般用于修改服务器上面的数据,使用post,其他的就用get吧</li></ul><h4 id="head"><a href="#head" class="headerlink" title="head"></a>head</h4><p>类似get请求,只不过响应中没有具体的内容,用于获取报头的,一般你不会用</p><h4 id="delete"><a href="#delete" class="headerlink" title="delete"></a>delete</h4><p>请求服务器删除指定的资源的</p><h4 id="put"><a href="#put" class="headerlink" title="put"></a>put</h4><p>从客户端向服务器传送指定的内容</p><h4 id="patch"><a href="#patch" class="headerlink" title="patch"></a>patch</h4><p>请求修改局部内容</p><h4 id="options"><a href="#options" class="headerlink" title="options"></a>options</h4><p>返回URL支持所有的HTTP方法</p><h3 id="set-default-headers-方法"><a href="#set-default-headers-方法" class="headerlink" title="set_default_headers()方法"></a>set_default_headers()方法</h3><h3 id="write-error-方法"><a href="#write-error-方法" class="headerlink" title="write_error()方法"></a>write_error()方法</h3><h3 id="on-finish-方法"><a href="#on-finish-方法" class="headerlink" title="on_finish()方法"></a>on_finish()方法</h3><ul><li>作用:在请求处理结束后调用</li><li>应用:<ul><li>我们能在改方法中进行一个资源的清理释放</li><li>或者说一个日志的处理<br>这个内存释放,我们通常不处理,以为这个python也有自带的垃圾回收机制</li><li>我们可以对于数据分析的原资料</li><li>比如对于访客的身份统计,喜好判断,对于调整本站的内容排行有所参考</li></ul></li><li>注意:<ul><li>尽量不要在该方法中进行相应输出    </li><li>这里做的是服务器内部的一些处理,不能关客户端的事儿</li></ul></li></ul><h2 id="我们可以进行打印出来看一看"><a href="#我们可以进行打印出来看一看" class="headerlink" title="我们可以进行打印出来看一看"></a>我们可以进行打印出来看一看</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initialize</span>(<span class="params">self</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        print(<span class="string">&quot;init_initialize&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">prepare</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(<span class="string">&quot;prepare&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(<span class="string">&quot;get_start&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">set_default_headers</span>(<span class="params">self</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        print(<span class="string">&quot;:set_default_headers&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">write_error</span>(<span class="params">self, status_code: <span class="built_in">int</span>, **kwargs: Any</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        print(<span class="string">&quot;write_error&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_finish</span>(<span class="params">self</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        print(<span class="string">&quot;on_finish&quot;</span>)</span><br><span class="line"></span><br><span class="line">```    </span><br><span class="line"></span><br><span class="line">执行的结果顺序如下</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">```shell script</span><br><span class="line">:set_default_headers</span><br><span class="line">init_initialize</span><br><span class="line">prepare</span><br><span class="line">get_start</span><br><span class="line">on_finish</span><br></pre></td></tr></table></figure><p>另一种方式,带有错误的情况</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initialize</span>(<span class="params">self</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        print(<span class="string">&quot;init_initialize&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">prepare</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(<span class="string">&quot;prepare&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.send_error(<span class="number">500</span>)</span><br><span class="line">        print(<span class="string">&quot;get_start&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">set_default_headers</span>(<span class="params">self</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        print(<span class="string">&quot;:set_default_headers&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">write_error</span>(<span class="params">self, status_code: <span class="built_in">int</span>, **kwargs: Any</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        print(<span class="string">&quot;write_error&quot;</span>)</span><br><span class="line">        self.write(<span class="string">&quot;服务器内部错误!!!&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_finish</span>(<span class="params">self</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        print(<span class="string">&quot;on_finish&quot;</span>)</span><br></pre></td></tr></table></figure><p>执行的结果顺序如下</p><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">:set_default_headers</span><br><span class="line">init_initialize</span><br><span class="line">prepare</span><br><span class="line">:set_default_headers</span><br><span class="line">write_error</span><br><span class="line">on_finish</span><br><span class="line">get_start</span><br></pre></td></tr></table></figure><h2 id="执行的顺序总结"><a href="#执行的顺序总结" class="headerlink" title="执行的顺序总结"></a>执行的顺序总结</h2><ul><li>在正常情况下,没抛出错误时<ul><li>:set_default_headers:设置头</li><li>init_initialize:初始化处理</li><li>prepare:预处理,预处理也需要头,所以在他后面</li><li>get_start:开始处理</li><li>on_finish:善后</li></ul></li><li>抛出错误时<ul><li>set_default_headers:</li><li>init_initialize:</li><li>prepare:</li><li>set_default_headers:又重新执行了一遍头,这里</li><li>write_error:</li><li>on_finish:</li><li>get_start:</li></ul></li></ul><p>这个顺序你得记住,其实也不用,你要是忘了就回来看就行了,但是你要理解其中的每个函数的作用</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> tornado </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tornado学习笔记day05</title>
      <link href="python/tornado/tornado-note5/"/>
      <url>python/tornado/tornado-note5/</url>
      
        <content type="html"><![CDATA[<h1 id="模板"><a href="#模板" class="headerlink" title="模板"></a>模板</h1><h2 id="配置模板路径"><a href="#配置模板路径" class="headerlink" title="配置模板路径"></a>配置模板路径</h2><p>这个在之前我们已经配置好了,可以参考前面的文章</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">settings = &#123;</span><br><span class="line">    <span class="comment"># 就像upfile就没有,你写了也白扯</span></span><br><span class="line">    <span class="string">&#x27;template_path&#x27;</span>: os.path.join(BASE_DIR, <span class="string">&quot;templates&quot;</span>),</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="渲染并返回给客户端"><a href="#渲染并返回给客户端" class="headerlink" title="渲染并返回给客户端"></a>渲染并返回给客户端</h2><p>使用render()方法</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HomeIndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.render(<span class="string">&quot;home.html&quot;</span>)</span><br></pre></td></tr></table></figure><h2 id="变量与表达式"><a href="#变量与表达式" class="headerlink" title="变量与表达式"></a>变量与表达式</h2><h3 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h3><ul><li>{ { var } }</li><li>{ { expression } }<h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HomeIndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        temp = <span class="number">100</span></span><br><span class="line">        <span class="comment"># 直接传一个变量就行</span></span><br><span class="line">        self.render(<span class="string">&quot;home.html&quot;</span>,num = temp)</span><br><span class="line">        <span class="comment"># self.render(&quot;home.html&quot;)</span></span><br></pre></td></tr></table></figure></li></ul><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>主页<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">h1</span>&gt;</span>这里是主页<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">   &#123; &#123; num &#125; &#125;</span><br><span class="line">   <span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">   <span class="comment">&lt;!-- 这里支持加减  --&gt;</span></span><br><span class="line">   &#123; &#123; num + 1 &#125; &#125;</span><br><span class="line">   &#123; &#123; num + 18 &#125; &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">&lt;!-- 这里需要用模板的注释才能真正的注释掉双大括号 --&gt;</span></span><br><span class="line">   <span class="comment">&lt;!-- 这里一定要注意,这个普通的注释会被加载到页面中 --&gt;</span></span><br><span class="line">   &#123;# num: &#123; &#123; num &#125; &#125; #&#125;</span><br><span class="line">   <span class="comment">&lt;!-- 模板的注释才是真正的注释 --&gt;</span></span><br><span class="line">   &#123;# num: &#123; &#123; num + 10 &#125; &#125; #&#125;</span><br><span class="line">   <span class="comment">&lt;!-- 等号的赋值的不好使的,会报错  --&gt;</span></span><br><span class="line">   &#123;# num: &#123; &#123; num = 5&#125; &#125; #&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="流程控制"><a href="#流程控制" class="headerlink" title="流程控制"></a>流程控制</h2><h3 id="if"><a href="#if" class="headerlink" title="if"></a>if</h3><h4 id="格式"><a href="#格式" class="headerlink" title="格式"></a>格式</h4><p>单个的if</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123; % if表达式 % &#125;</span><br><span class="line">语句</span><br><span class="line">&#123; % end % &#125;</span><br></pre></td></tr></table></figure><p>if和else的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123; % if表达式 % &#125;</span><br><span class="line">语句1</span><br><span class="line">&#123; % else % &#125;</span><br><span class="line">语句2</span><br><span class="line">&#123; % end % &#125;</span><br></pre></td></tr></table></figure><p>多个if 的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123; % if表达式1 % &#125;</span><br><span class="line">语句1</span><br><span class="line">&#123; % elif 表达式2% &#125;</span><br><span class="line">语句2</span><br><span class="line">&#123; % elif 表达式3% &#125;</span><br><span class="line">语句3</span><br><span class="line">&lt;!--这里面else可有可无--&gt;</span><br><span class="line">&#123; % end % &#125;</span><br></pre></td></tr></table></figure><h4 id="实例-1"><a href="#实例-1" class="headerlink" title="实例"></a>实例</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#123; % if flag &#x3D;&#x3D; 0% &#125;</span><br><span class="line">flag确实是0</span><br><span class="line">&#123; % elif flag &#x3D;&#x3D; 0 % </span><br><span class="line">语句2</span><br><span class="line">&#123; % elif flag &#x3D;&#x3D; 2 % &#125;</span><br><span class="line">flag bug</span><br><span class="line">&#123; % else % &#125;</span><br><span class="line">baiche</span><br><span class="line">&#123; % end % &#125;</span><br></pre></td></tr></table></figure><h3 id="for"><a href="#for" class="headerlink" title="for"></a>for</h3><p>这里面需要注意的是,结束模板语法都是<code> &#123; % end % &#125;</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123; % for 变量 in 集合 % &#125;</span><br><span class="line">语句</span><br><span class="line">&#123; % end % &#125;</span><br></pre></td></tr></table></figure><p>实例:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;ul&gt;</span><br><span class="line">    &#123; % for stu in stus % &#125;</span><br><span class="line">    &lt;li&gt;&#123; &#123; stu &#125; &#125;&lt;&#x2F;li&gt;</span><br><span class="line">    &#123; % end % &#125;</span><br><span class="line">&lt;&#x2F;ul&gt;</span><br></pre></td></tr></table></figure><h3 id="while"><a href="#while" class="headerlink" title="while"></a>while</h3><p>这个while很少使用,就不写了</p><h2 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h2><h3 id="static-url"><a href="#static-url" class="headerlink" title="static_url()"></a>static_url()</h3><h4 id="作用"><a href="#作用" class="headerlink" title="作用"></a>作用</h4><ul><li>获取配置中的静态目录的路径</li><li>将参数拼接到静态目录后面并返回新的路径<h4 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;link rel&#x3D;&quot;stylesheet&quot; href&#x3D;&quot;&#123; &#123; static_url(&#39;css&#x2F;home.css&#39;) &#125; &#125;&quot;&gt;</span><br></pre></td></tr></table></figure><h4 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h4></li><li>修改目录的话 只需要修改配置文件中的内容即可,不需要修改各种页面中的URL</li><li>Hash值<ul><li>static_url创建了基于文件内容的Hash值</li><li>将其添加到文件的末尾(当一个查询参数)</li><li>这个hash值总能够保证,我们每一次加载最新的版本</li><li>而不是之前的缓存的版本</li><li>不论是开发阶段还是线上阶段,都是很有必要的</li></ul></li></ul><h2 id="转义"><a href="#转义" class="headerlink" title="转义"></a>转义</h2><p>tornado默认开启自动转义功能,能够防止网站攻击</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TranHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">str</span> = <span class="string">&quot;&lt;h1&gt;能不能转义就看这会的了&lt;/h1&gt;&quot;</span></span><br><span class="line">        self.render(<span class="string">&quot;trans.html&quot;</span>,<span class="built_in">str</span> = <span class="built_in">str</span>)</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang&#x3D;&quot;en&quot;&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;meta charset&#x3D;&quot;UTF-8&quot;&gt;</span><br><span class="line">    &lt;title&gt;转义&lt;&#x2F;title&gt;</span><br><span class="line">&lt;&#x2F;head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&#123; &#123;str&#125; &#125;</span><br><span class="line">&lt;&#x2F;body&gt;</span><br><span class="line">&lt;&#x2F;html&gt;</span><br></pre></td></tr></table></figure><p>页面这样显示</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;h1&gt;能不能转义就看这会的了&lt;&#x2F;h1&gt;</span><br></pre></td></tr></table></figure><h3 id="关闭自动转义"><a href="#关闭自动转义" class="headerlink" title="关闭自动转义"></a>关闭自动转义</h3><ul><li>raw:<code>&#123; % raw str % &#125;</code>这个会关闭一行</li><li>在页面模板中修改<ul><li>autoescape:<code>&#123; % autoescape None % &#125;</code></li><li>这个不管你三七二十一都关闭了就</li></ul></li><li>在配置文件中修改 <ul><li><code>autoescape : None</code> </li><li>当为None时关闭当前项目的自动转义</li></ul></li><li>escape()函数<ul><li>这个函数能够在全局转义的条件下再不转义</li><li><code>&#123; &#123; escape(str) &#125; &#125;</code>    </li></ul></li></ul><h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2><h2 id="静态文件"><a href="#静态文件" class="headerlink" title="静态文件"></a>静态文件</h2><ul><li>static_path<ul><li>作用<ul><li>告诉tornado从文件系统中某一个特定的位置提供我们的静态文件</li></ul></li><li>示例:<code>&#39;static_path&#39;: os.path.join(BASE_DIR, &quot;static&quot;),</code></li><li>请求方式:<code>http://127.0.0.1:8080/static/html/index.html</code></li><li>引用其他文件:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;link rel&#x3D;&quot;stylesheet&quot; href&#x3D;&quot;&#123; &#123;static_url(&#39;css&#x2F;index.css&#39;)&#125; &#125;&quot;&gt;</span><br><span class="line">&lt;script src&#x3D;&quot;&#123; &#123;static_url(&#39;js&#x2F;jquery.js&#39;)&#125; &#125;&quot;&gt;&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure></li></ul></li><li>StaticFileHandler <ul><li>使用原因:这种请求方式:<code>http://127.0.0.1:8080/static/html/index.html</code>对于用户来说,体验不佳</li><li>本质: 是tornado预制的用来提供静态资源文件的Handler</li><li>作用: 可以通过StaticFileHandler来映射静态资源文件</li><li>使用:<ul><li>第一种写法<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">(<span class="string">r&quot;/(.*)$&quot;</span>, tornado.web.StaticFileHandler,&#123;</span><br><span class="line">                <span class="string">&quot;path&quot;</span>:os.path.join(BASE_DIR,<span class="string">&quot;static/html&quot;</span>),</span><br><span class="line">            &#125;),</span><br></pre></td></tr></table></figure></li><li>第二种:<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">(</span><br><span class="line">    <span class="string">r&quot;/(.*)$&quot;</span>,</span><br><span class="line">    tornado.web.StaticFileHandler,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="string">&quot;path&quot;</span>: os.path.join(BASE_DIR, <span class="string">&quot;static/html&quot;</span>),</span><br><span class="line">        <span class="string">&quot;default_filename&quot;</span>: <span class="string">&quot;index.html&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">),</span><br></pre></td></tr></table></figure></li></ul></li><li>参数:<ul><li>path:用来指定访问提供静态文件根路径</li><li>default_filename:用来指定访问路由中未指定文件名时,访问哪个静态中的文件</li></ul></li><li>注意:<ul><li>最好在其他路由的最下面写</li><li>否则可能会不匹配</li><li>其中的路由可以去参考一下<a href="https://www.baidu.com/">百度</a>的</li></ul></li></ul></li></ul><h1 id="数据库"><a href="#数据库" class="headerlink" title="数据库"></a>数据库</h1><h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p>tornado目前没有自己的数据库,需要连接数据库,还得自己去适配<br>目前python3.6+tornado还没有完善的驱动  </p><h3 id="磁盘数据库和内存数据库"><a href="#磁盘数据库和内存数据库" class="headerlink" title="磁盘数据库和内存数据库:"></a>磁盘数据库和内存数据库:</h3><p>比如你以前你的爸爸,那个手机啊,欠费了好几十还不给你停机<br>因为数据还没来得及处理,那个话费单,得一条一条处理,他处理不过来,知道么,当你欠费的时候,他还不知道你欠费呢<br>现在就不一样了,你的话单数据都在内存里面了,你一旦欠费,马上就给你停机,O(∩_∩)O哈哈~</p><p>redis的开源的内存数据库,移动联通都不用这种数据库<br>内存数据库是国内06年开始有人在搞<br>从13年开始,又出现了一个分布式内存数据库,现在人们都有钱了,数据量大了,一台服务器都存不下了<br>14年开始,又升级了一下,这次升级的是硬件,以前用的是万兆网卡,现在更NB了 </p><h3 id="链接"><a href="#链接" class="headerlink" title="链接"></a>链接</h3><p>在应用启动时,创建一个数据库链接实例,供各个requestHandler使用</p><p>在requestHandler中,通过self.application来获取对象</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> tornado </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tornado学习笔记day02</title>
      <link href="python/tornado/tornado-note2/"/>
      <url>python/tornado/tornado-note2/</url>
      
        <content type="html"><![CDATA[<h1 id="整理基础工程"><a href="#整理基础工程" class="headerlink" title="整理基础工程"></a>整理基础工程</h1><ul><li>请看第一天的配置文件目录,搭建了一个框架的基础目录<h1 id="Application"><a href="#Application" class="headerlink" title="Application"></a>Application</h1><h2 id="settings"><a href="#settings" class="headerlink" title="settings"></a>settings</h2><h3 id="debug"><a href="#debug" class="headerlink" title="debug"></a>debug</h3><h4 id="作用"><a href="#作用" class="headerlink" title="作用"></a>作用</h4>可以设置tornado是否工作在调试模式下面,默认为false,即工作在生产模式下<h4 id="true的特性"><a href="#true的特性" class="headerlink" title="true的特性:"></a>true的特性:</h4><h5 id="自动重启"><a href="#自动重启" class="headerlink" title="自动重启:"></a>自动重启:</h5></li><li>tornado程序会监控源代码文件,会自动重启服务器,减少我们手动重启的次数,提高开发效率</li><li>如果保存后有错误,导致重启失败,修改好后,不会再重启了,需要我们手动进行重新启动</li><li>在debug开启后,那四个特性咱也不太会啊,咱就想着能够重启就得了,那这可咋整,这个时候我们可以通过<code>&quot;autoreload&quot; : True</code>设置,仅仅有第一个特性<h5 id="取消缓存编译的模板"><a href="#取消缓存编译的模板" class="headerlink" title="取消缓存编译的模板:"></a>取消缓存编译的模板:</h5></li><li>单独设置:<code>compiled_template_cache = False</code></li><li>,这个默认值为<code>true</code>,这里要注意不是说我<code>debug</code>设置默认为啥,里面就默认都是啥</li><li>你改完了模板的内容,它得加载你改了的啊,不能还用缓存的内容,要不然你看不到修改的新结果,这可不行</li><li>虽然出于性能考虑,老也重新加载有点儿慢,但是没事儿,毕竟开发中也不差这一点资源<h5 id="取消缓存静态文件的HASH值"><a href="#取消缓存静态文件的HASH值" class="headerlink" title="取消缓存静态文件的HASH值"></a>取消缓存静态文件的HASH值</h5></li><li>单独设置:<code>static_hash_cache = False</code></li><li>css文件每次后面都有一个哈希值,这个哈希值能缓存</li><li>这样我们都能重新加载这个css就OK了<h5 id="提供追踪信息"><a href="#提供追踪信息" class="headerlink" title="提供追踪信息"></a>提供追踪信息</h5></li><li>如果我们的IndexHandler里面抛出了一个异常,但是他自己没有捕获这个异常,就会生成一个追踪的页面</li><li>单独设置:<code>serve_traceback = True</code><h3 id="template-path"><a href="#template-path" class="headerlink" title="template_path:"></a>template_path:</h3>设置模板文件目录<h3 id="static-path"><a href="#static-path" class="headerlink" title="static_path :"></a>static_path :</h3>设置静态文件目录<h3 id="auto-escape"><a href="#auto-escape" class="headerlink" title="auto_escape :"></a>auto_escape :</h3>当为None时,关闭项目的自动转义<h3 id="cookie-secret"><a href="#cookie-secret" class="headerlink" title="cookie_secret:"></a>cookie_secret:</h3>配置安全cookie秘钥<h3 id="xsrf-cookie"><a href="#xsrf-cookie" class="headerlink" title="xsrf_cookie:"></a>xsrf_cookie:</h3>当为True,开启XSRF保护<h3 id="login-url"><a href="#login-url" class="headerlink" title="login_url"></a>login_url</h3>用于定义登录的路径,默认找这里<h2 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h2></li><li><code>(r&quot;/&quot;, index.IndexHandler),</code></li><li>传的参数在路由那嘎达的字典类型的数据</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">D:.</span><br><span class="line">│  config.py</span><br><span class="line">│  readme.md</span><br><span class="line">│  server.py</span><br><span class="line">│  application.py</span><br><span class="line">│  </span><br><span class="line">├─.idea</span><br><span class="line">│  │  .gitignore</span><br><span class="line">│  │  itcast_tornado.iml</span><br><span class="line">│  │  misc.xml</span><br><span class="line">│  │  modules.xml</span><br><span class="line">│  │  vcs.xml</span><br><span class="line">│  │  workspace.xml</span><br><span class="line">│  │</span><br><span class="line">│  └─inspectionProfiles</span><br><span class="line">│          profiles_settings.xml</span><br><span class="line">│</span><br><span class="line">├─static # 静态资源文件夹    </span><br><span class="line">├─templates # 模板文件</span><br><span class="line">├─upfile  # 上传文件</span><br><span class="line">│</span><br><span class="line">└─views # 视图</span><br><span class="line">   │  index.py # 首页视图</span><br><span class="line">   └─ __init__.py</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="version1-0"><a href="#version1-0" class="headerlink" title="version1.0"></a>version1.0</h2><p>创建一个<code>index.py</code>文件在<code>views</code>包下面,内容如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> tornado.web <span class="keyword">import</span> RequestHandler</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在<code>server.py</code>文件中修改如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="keyword">import</span> tornado.ioloop</span><br><span class="line"><span class="keyword">import</span> tornado.httpserver</span><br><span class="line"><span class="keyword">import</span> tornado.options</span><br><span class="line"><span class="keyword">import</span> config</span><br><span class="line"><span class="keyword">from</span> views.index <span class="keyword">import</span> IndexHandler</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app = tornado.web.Application(</span><br><span class="line">        [</span><br><span class="line">            (<span class="string">r&quot;/&quot;</span>, IndexHandler)</span><br><span class="line">        ]</span><br><span class="line">    )</span><br><span class="line">    httpServer = tornado.httpserver.HTTPServer(app)</span><br><span class="line">    httpServer.bind(config.options[<span class="string">&quot;port&quot;</span>])</span><br><span class="line">    httpServer.start(<span class="number">1</span>)</span><br><span class="line">    tornado.ioloop.IOLoop.current().start()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>其中的<code>config.py</code>不用动</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">options = &#123;</span><br><span class="line">    <span class="string">&quot;port&quot;</span>: <span class="number">8080</span>,</span><br><span class="line">    <span class="string">&quot;list&quot;</span>: [<span class="string">&quot;good&quot;</span>, <span class="string">&quot;nice&quot;</span>, <span class="string">&quot;handsome&quot;</span>]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="version2-0"><a href="#version2-0" class="headerlink" title="version2.0"></a>version2.0</h2><p>创建一个<code>application.py</code>的文件,内容如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="keyword">from</span> views.index <span class="keyword">import</span> IndexHandler</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Application</span>(<span class="params">tornado.web.Application</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        handlers = [</span><br><span class="line">            (<span class="string">r&quot;/&quot;</span>, IndexHandler)</span><br><span class="line">        ]</span><br><span class="line">        <span class="built_in">super</span>(Application,self).__init__(handlers)</span><br></pre></td></tr></table></figure><p>然后服务端这么改</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.ioloop</span><br><span class="line"><span class="keyword">import</span> tornado.httpserver</span><br><span class="line"><span class="keyword">import</span> tornado.options</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> config</span><br><span class="line"><span class="keyword">from</span> application <span class="keyword">import</span> Application</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app = Application()</span><br><span class="line">    httpServer = tornado.httpserver.HTTPServer(app)</span><br><span class="line">    httpServer.bind(config.options[<span class="string">&quot;port&quot;</span>])</span><br><span class="line">    httpServer.start(<span class="number">1</span>)</span><br><span class="line">    tornado.ioloop.IOLoop.current().start()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>视图都不用动</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> tornado.web <span class="keyword">import</span> RequestHandler</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br></pre></td></tr></table></figure><p>因为tornado不是Django那种大而全的,而是小而精的</p><p>所以配置也不用怎么动</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 参数</span></span><br><span class="line">options = &#123;</span><br><span class="line">    <span class="string">&quot;port&quot;</span>: <span class="number">8080</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置</span></span><br><span class="line">settings = &#123;</span><br><span class="line">    <span class="comment"># static_path = &quot;/&quot;,</span></span><br><span class="line">    <span class="string">&quot;debug&quot;</span> : <span class="literal">True</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>成了这就</p><p>然后我们再配置一个路由<code>home</code><br>在application里面直接加就OK</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="keyword">from</span> views <span class="keyword">import</span> index</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Application</span>(<span class="params">tornado.web.Application</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        handlers = [</span><br><span class="line">            (<span class="string">r&quot;/&quot;</span>, index.IndexHandler),</span><br><span class="line">            (<span class="string">r&quot;/home&quot;</span>, index.HomeHandler),</span><br><span class="line">        ]</span><br><span class="line">        <span class="built_in">super</span>(Application,self).__init__(handlers)</span><br></pre></td></tr></table></figure><p>然后在视图中再创建一个对应的类</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> tornado.web <span class="keyword">import</span> RequestHandler</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HomeHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot; this is home page content!&quot;</span>)</span><br></pre></td></tr></table></figure><p>重启服务即可在浏览器中访问<code>http://127.0.0.1:8080/home</code>看到结果</p><h2 id="配置路径"><a href="#配置路径" class="headerlink" title="配置路径"></a>配置路径</h2><p>Django中的那个BASE_DIRS挺好用的,我们也想有一个,那我们也可以整</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line">BASE_DIR = os.path.dirname(__file__)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 参数</span></span><br><span class="line">options = &#123;</span><br><span class="line">    <span class="string">&quot;port&quot;</span>: <span class="number">8080</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置</span></span><br><span class="line">settings = &#123;</span><br><span class="line">    <span class="comment"># 这写key的名字可不是随便起的奥,是写好的,</span></span><br><span class="line">    <span class="comment"># 就像upfile就没有,你写了也白扯</span></span><br><span class="line">    <span class="string">&#x27;static_path&#x27;</span> : os.path.join(BASE_DIR,<span class="string">&quot;static&quot;</span>),</span><br><span class="line">    <span class="string">&#x27;template_path&#x27;</span> : os.path.join(BASE_DIR,<span class="string">&quot;templates&quot;</span>),</span><br><span class="line">    <span class="string">&quot;debug&quot;</span> : <span class="literal">True</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="路由参数的传递"><a href="#路由参数的传递" class="headerlink" title="路由参数的传递"></a>路由参数的传递</h2><p>传递的方式和Django差不多,但也有不同之处,这里直接上代码</p><p>路由里面这样发</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="keyword">from</span> views <span class="keyword">import</span> index</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Application</span>(<span class="params">tornado.web.Application</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        handlers = [</span><br><span class="line">            (<span class="string">r&quot;/&quot;</span>, index.IndexHandler),</span><br><span class="line">            (<span class="string">r&quot;/sunck&quot;</span>, index.SunckHandler,&#123;<span class="string">&#x27;name&#x27;</span>:<span class="string">&quot;victor&quot;</span>,<span class="string">&#x27;age&#x27;</span>:<span class="number">19</span>&#125;),</span><br><span class="line">        ]</span><br><span class="line">        <span class="built_in">super</span>(Application,self).__init__(handlers)</span><br></pre></td></tr></table></figure><p>视图里面这样接</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> tornado.web <span class="keyword">import</span> RequestHandler</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SunckHandler</span>(<span class="params">RequestHandler</span>):</span></span><br><span class="line">    <span class="comment"># 该方法会在HTTP方法之前调用</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initialize</span>(<span class="params">self,age,name</span>) -&gt; <span class="keyword">None</span>:</span></span><br><span class="line">        self.age = age</span><br><span class="line">        self.name = name</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(self.age)</span><br><span class="line">        print(self.name)</span><br><span class="line">        self.write(<span class="string">&quot;sunck page info tornado!&quot;</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>这里不能再get方法中直接加上参数接受</p><p>需要重写initialize方法,来对成员属性进行定义</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> tornado </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>2019 Python 面试 100 问</title>
      <link href="cp/python/python-interview3/"/>
      <url>cp/python/python-interview3/</url>
      
        <content type="html"><![CDATA[<meta itemprop="url" content="https://juejin.im/post/5cfd1d0d6fb9a07eaf2b844d"><meta itemprop="headline" content="2019 Python 面试 100 问"><meta itemprop="keywords" content="Python"><meta itemprop="datePublished" content="2019-06-09T14:53:04.194Z"><meta itemprop="image" content="https://b-gold-cdn.xitu.io/icon/icon-128.png"><div itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">    <meta itemprop="name" content="zone">    <meta itemprop="url" content="https://juejin.im/user/57b5caa1c4c971005f943975"></div><div itemprop="publisher" itemscope="itemscope" itemtype="http://schema.org/Organization">    <meta itemprop="name" content="掘金">    <div itemprop="logo" itemscope="itemscope" itemtype="https://schema.org/ImageObject">        <meta itemprop="url" content="https://b-gold-cdn.xitu.io/icon/icon-white-180.png">        <meta itemprop="width" content="180">        <meta itemprop="height" content="180">    </div></div><div data-v-0526462d="" class="author-info-block"><a data-v-0526462d="" href="/user/57b5caa1c4c971005f943975"                                                     target="_blank" rel="" class="avatar-link">    <div data-v-10f5e1e2="" data-v-762a6aba="" data-v-0526462d=""         data-src="https://user-gold-cdn.xitu.io/2016/11/29/87e4d156ebc6f2901cb96d320004af0e?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1"         class="lazy avatar avatar loaded"         style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2016/11/29/87e4d156ebc6f2901cb96d320004af0e?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div></a>    <div data-v-0526462d="" class="author-info-box"><a data-v-db47c888="" data-v-0526462d=""                                                       href="/user/57b5caa1c4c971005f943975" target="_blank" rel=""                                                       class="username username ellipsis">zone<a data-v-0ba9b815=""                                                                                                 data-v-db47c888=""                                                                                                 href="/book/5c90640c5188252d7941f5bb/section/5c9065385188252da6320022"                                                                                                 target="_blank"                                                                                                 rel=""                                                                                                 class="rank"><img            data-v-0ba9b815="" src="https://b-gold-cdn.xitu.io/v3/static/img/lv-2.f597b88.svg" alt="lv-2"></a></a>        <div data-v-0526462d="" class="meta-box">            <time data-v-0526462d="" datetime="2019-06-09T14:53:04.194Z"                  title="Sun Jun 09 2019 22:53:04 GMT+0800 (中国标准时间)" class="time">2019年06月09日            </time>            <span data-v-0526462d="" class="views-count">阅读 3019</span><!----></div>    </div>    <button data-v-0bccdb0e="" data-v-0526462d="" class="follow-button follow">关注</button></div><!----><h1 data-v-0526462d="" class="article-title">2019 Python 面试 100 问</h1><div data-v-0526462d="" data-id="5cfd1d506fb9a07eaf2b844e" itemprop="articleBody" class="article-content"><h2        class="heading" data-id="heading-0">以下内容出自小程序「编程面试题库」，本文首发于公众号「zone7」</h2>    <p></p>    <figure><img class="lazyload inited loaded"                 data-src="https://user-gold-cdn.xitu.io/2019/6/9/16b3cb978e19876a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1"                 data-width="1087" data-height="455"                 src="https://user-gold-cdn.xitu.io/2019/6/9/16b3cb978e19876a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1">        <figcaption></figcaption>    </figure>    <p></p>    <h2 class="heading" data-id="heading-1">0 遇到过得反爬虫策略以及解决方法?</h2>    <p>1.通过headers反爬虫        2.基于用户行为的发爬虫：(同一IP短时间内访问的频率)        3.动态网页反爬虫(通过ajax请求数据，或者通过JavaScript生成)        4.对部分数据进行加密处理的(数据是乱码)</p>    <h3 class="heading" data-id="heading-2">解决方法：</h3>    <p>对于基本网页的抓取可以自定义headers,添加headers的数据        使用多个代理ip进行抓取或者设置抓取的频率降低一些，        动态网页的可以使用selenium + phantomjs 进行抓取        对部分数据进行加密的，可以使用selenium进行截图，使用python自带的pytesseract库进行识别，但是比较慢最直接的方法是找到加密的方法进行逆向推理。</p>    <h2 class="heading" data-id="heading-3">1 urllib 和 urllib2 的区别？</h2>    <ul>        <li>urllib            和urllib2都是接受URL请求的相关模块，但是urllib2可以接受一个Request类的实例来设置URL请求的headers，urllib仅可以接受URL。urllib不可以伪装你的User-Agent字符串。        </li>        <li>urllib提供urlencode()方法用来GET查询字符串的产生，而urllib2没有。这是为何urllib常和urllib2一起使用的原因。</li>    </ul>    <h2 class="heading" data-id="heading-4">2 列举网络爬虫所用到的网络数据包，解析包？</h2>    <ul>        <li>网络数据包 urllib、urllib2、requests</li>        <li>解析包 re、xpath、beautiful soup、lxml</li>    </ul>    <h2 class="heading" data-id="heading-5">3 简述一下爬虫的步骤？</h2>    <ol>        <li>确定需求；</li>        <li>确定资源；</li>        <li>通过url获取网站的返回数据；</li>        <li>定位数据；</li>        <li>存储数据。</li>    </ol>    <h2 class="heading" data-id="heading-6">4 遇到反爬机制怎么处理？</h2>    <h2 class="heading" data-id="heading-7">反爬机制:</h2>    <p>headers方向        判断User-Agent、判断Referer、判断Cookie。        将浏览器的headers信息全部添加进去        注意：Accept-Encoding；gzip,deflate需要注释掉</p>    <h2 class="heading" data-id="heading-8">5 常见的HTTP方法有哪些？</h2>    <ul>        <li>GET：请求指定的页面信息，返回实体主体；</li>        <li>HEAD:类似于get请求，只不过返回的响应中没有具体的内容，用于捕获报头；</li>        <li>POST：向指定资源提交数据进行处理请求(比如表单提交或者上传文件)，。数据被包含在请求体中。</li>        <li>PUT:从客户端向服务端传送数据取代指定的文档的内容；</li>        <li>DELETE：请求删除指定的页面；</li>        <li>CONNNECT：HTTP1.1协议中预留给能够将连接方式改为管道方式的代理服务器；</li>        <li>OPTIONS:允许客户端查看服务器的性能；            TRACE：回显服务器的请求，主要用于测试或者诊断。        </li>    </ul>    <h2 class="heading" data-id="heading-9">6 说一说redis-scrapy中redis的作用?</h2>    <p>它是将scrapy框架中Scheduler替换为redis数据库，实现队列管理共享。</p>    <h3 class="heading" data-id="heading-10">优点：</h3>    <ol>        <li>可以充分利用多台机器的带宽；</li>        <li>可以充分利用多台机器的IP地址。</li>    </ol>    <h2 class="heading" data-id="heading-11">7 遇到的反爬虫策略以及解决方法?</h2>    <ol>        <li>通过headers反爬虫：自定义headers，添加网页中的headers数据。</li>        <li>基于用户行为的反爬虫(封IP)：可以使用多个代理IP爬取或者将爬取的频率降低。</li>        <li>动态网页反爬虫(JS或者Ajax请求数据)：动态网页可以使用 selenium + phantomjs 抓取。</li>        <li>对部分数据加密处理(数据乱码):找到加密方法进行逆向推理。</li>    </ol>    <h2 class="heading" data-id="heading-12">8 如果让你来防范网站爬虫，你应该怎么来提高爬取的难度 ？</h2>    <ol>        <li>判断headers的User-Agent；</li>        <li>检测同一个IP的访问频率；</li>        <li>数据通过Ajax获取；</li>        <li>爬取行为是对页面的源文件爬取，如果要爬取静态网页的html代码，可以使用jquery去模仿写html。</li>    </ol>    <h2 class="heading" data-id="heading-13">9 scrapy分为几个组成部分？分别有什么作用？</h2>    <p>分为5个部分；Spiders(爬虫类)，Scrapy Engine(引擎),Scheduler(调度器),Downloader(下载器),Item Pipeline(处理管道)。</p>    <ul>        <li>Spiders:开发者自定义的一个类，用来解析网页并抓取指定url返回的内容。</li>        <li>Scrapy Engine:控制整个系统的数据处理流程，并进行事务处理的触发。</li>        <li>Scheduler：接收Engine发出的requests，并将这些requests放入到处理列队中，以便之后engine需要时再提供。</li>        <li>Download：抓取网页信息提供给engine，进而转发至Spiders。</li>        <li>Item Pipeline:负责处理Spiders类提取之后的数据。            比如清理HTML数据、验证爬取的数据(检查item包含某些字段)、查重(并丢弃)、将爬取结果保存到数据库中        </li>    </ul>    <h2 class="heading" data-id="heading-14">10 简述一下scrapy的基本流程?</h2>    <p></p>    <figure><img alt="image" class="lazyload inited loaded"                 data-src="https://user-gold-cdn.xitu.io/2019/6/9/16b3cb978e4c62a1?imageView2/0/w/1280/h/960/format/webp/ignore-error/1"                 data-width="800" data-height="537"                 src="https://user-gold-cdn.xitu.io/2019/6/9/16b3cb978e4c62a1?imageView2/0/w/1280/h/960/format/webp/ignore-error/1">        <figcaption></figcaption>    </figure>    <p></p>    <h2 class="heading" data-id="heading-15">scrapy分为9个步骤：</h2>    <ol>        <li>Spiders需要初始的start_url或则函数stsrt_requests,会在内部生成Requests给Engine；</li>        <li>Engine将requests发送给Scheduler;</li>        <li>Engine从Scheduler那获取requests,交给Download下载；</li>        <li>在交给Dowmload过程中会经过Downloader Middlewares(经过process_request函数)；</li>        <li>Dowmloader下载页面后生成一个response，这个response会传给Engine，这个过程中又经过了Downloader            Middlerwares(经过process_request函数)，在传送中出错的话经过process_exception函数；        </li>        <li>Engine将从Downloader那传送过来的response发送给Spiders处理，这个过程经过Spiders Middlerwares(经过process_spider_input函数)；</li>        <li>Spiders处理这个response，返回Requests或者Item两个类型，传给Engine，这个过程又经过Spiders            Middlewares(经过porcess_spider_output函数)；        </li>        <li>Engine接收返回的信息，如果使Item，将它传给Items Pipeline中；如果是Requests,将它传给Scheduler，继续爬虫；</li>        <li>重复第三步，直至没有任何需要爬取的数据</li>    </ol>    <h2 class="heading" data-id="heading-16">11 python3.5语言中enumerate的意思是</h2>    <p>对于一个可迭代的（iterable）/可遍历的对象（如列表、字符串），enumerate将其组成一个索引序列，利用它可以同时获得索引和值        enumerate多用于在for循环中得到计数</p>    <h2 class="heading" data-id="heading-17">12 你是否了解谷歌的无头浏览器？</h2>    <p>无头浏览器即headless browser，是一种没有界面的浏览器。既然是浏览器那么浏览器该有的东西它都应该有，只是看不到界面而已。</p>    <p>Python中selenium模块中的PhantomJS即为无界面浏览器（无头浏览器）:是基于QtWebkit的无头浏览器。</p>    <h2 class="heading" data-id="heading-18">13 scrapy和scrapy-redis的区别？</h2>    <p>scrapy是一个爬虫通用框架，但不支持分布式，scrapy-redis是为了更方便的实现scrapy分布式爬虫，而提供了一些以redis为基础的组件</p>    <h2 class="heading" data-id="heading-19">为什么会选择redis数据库？</h2>    <p>因为redis支持主从同步，而且数据都是缓存在内存中，所以基于redis的分布式爬虫，对请求和数据的高频读取效率非常高</p>    <h2 class="heading" data-id="heading-20">什么是主从同步？</h2>    <p>        在Redis中，用户可以通过执行SLAVEOF命令或者设置slaveof选项，让一个服务器去复制（replicate）另一个服务器，我们称呼被复制的服务器为主服务器（master），而对主服务器进行复制的服务器则被称为从服务器（slave），当客户端向从服务器发送SLAVEOF命令，要求从服务器复制主服务器时，从服务器首先需要执行同步操作，也即是，将从服务器的数据库状态更新至主服务器当前所处的数据库状态</p>    <h2 class="heading" data-id="heading-21">14 scrapy的优缺点？为什么要选择scrapy框架？</h2>    <h3 class="heading" data-id="heading-22">优点：</h3>    <p>采取可读性更强的xpath代替正则&nbsp;强大的统计和log系统&nbsp;同时在不同的url上爬行&nbsp;支持shell方式，方便独立调试&nbsp;写middleware,方便写一些统一的过滤器&nbsp;通过管道的方式存入数据库</p>    <h3 class="heading" data-id="heading-23">缺点：</h3>    <p>基于python爬虫框架，扩展性比较差，基于twisted框架，运行中exception是不会干掉reactor，并且异步框架出错后是不会停掉其他任务的，数据出错后难以察觉</p>    <h2 class="heading" data-id="heading-24">15 scrapy和requests的使用情况？</h2>    <p>requests 是 polling 方式的，会被网络阻塞，不适合爬取大量数据</p>    <p>scapy 底层是异步框架 twisted ，并发是最大优势</p>    <h2 class="heading" data-id="heading-25">16 描述一下scrapy框架的运行机制？</h2>    <p>        从start_urls里面获取第一批url发送请求，请求由请求引擎给调度器入请求对列，获取完毕后，调度器将请求对列交给下载器去获取请求对应的响应资源，并将响应交给自己编写的解析方法做提取处理，如果提取出需要的数据，则交给管道处理，如果提取出url，则继续执行之前的步骤，直到多列里没有请求，程序结束。</p>    <h2 class="heading" data-id="heading-26">17 写爬虫使用多进程好，还是用多线程好？</h2>    <p>        IO密集型代码(文件处理、网络爬虫等)，多线程能够有效提升效率(单线程下有IO操作会进行IO等待，造成不必要的时间浪费，而开启多线程能在线程A等待时，自动切换到线程B，可以不浪费CPU的资源，从而能提升程序执行效率)。在实际的数据采集过程中，既考虑网速和响应的问题，也需要考虑自身机器的硬件情况，来设置多进程或多线程</p>    <h2 class="heading" data-id="heading-27">18 常见的反爬虫和应对方法？</h2>    <ol>        <li>基于用户行为，同一个ip段时间多次访问同一页面&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;利用代理ip，构建ip池</li>        <li>请求头里的user-agent&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;构建user-agent池（操作系统、浏览器不同，模拟不同用户）</li>        <li>动态加载（抓到的数据和浏览器显示的不一样），js渲染&nbsp;&nbsp;&nbsp;&nbsp;模拟ajax请求，返回json形式的数据</li>        <li>selenium / webdriver 模拟浏览器加载</li>        <li>对抓到的数据进行分析</li>        <li>加密参数字段&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;会话跟踪【cookie】&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 防盗链设置【Referer</li>    </ol>    <h2 class="heading" data-id="heading-28">19 分布式爬虫主要解决什么问题？</h2>    <p>面对海量待抓取网页，只有采用分布式架构，才有可能在较短时间内完成一轮抓取工作。</p>    <p>它的开发效率是比较快而且简单的。</p>    <h2 class="heading" data-id="heading-29">20 如何提高爬取效率？</h2>    <p>爬虫下载慢主要原因是阻塞等待发往网站的请求和网站返回</p>    <pre><code class="copyable">    1，采用异步与多线程，扩大电脑的cpu利用率；<pre><code>2，采用消息队列模式3，提高带宽</code></pre><p><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-30">21 说说什么是爬虫协议？</h2><br>    <p>Robots协议（也称为爬虫协议、爬虫规则、机器人协议等）也就是robots.txt，网站通过robots协议告诉搜索引擎哪些页面可以抓取，哪些页面不能抓取。</p><br>    <p>Robots协议是网站国际互联网界通行的道德规范，其目的是保护网站数据和敏感信息、确保用户个人信息和隐私不被侵犯。因其不是命令，故需要搜索引擎自觉遵守。</p><br>    <h2 class="heading" data-id="heading-31">22 如果对方网站反爬取，封IP了怎么办？</h2><br>    <ol><br>        <li>放慢抓取熟速度，减小对目标网站造成的压力，但是这样会减少单位时间内的数据抓取量</li><br>        <li>使用代理IP（免费的可能不稳定，收费的可能不划算）</li><br>    </ol><br>    <h2 class="heading" data-id="heading-32">23 有一个jsonline格式的文件file</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">get_lines</span><span            class="hljs-params">()</span>:</span><br>    <span class="hljs-keyword">with</span> open(<span class="hljs-string">'file.txt'</span>,<span class="hljs-string">'rb'</span>) <span                class="hljs-keyword">as</span> f:<br>        <span class="hljs-keyword">return</span> f.readlines()</p><p><span class="hljs-keyword">if</span> <strong>name</strong> == <span class="hljs-string">‘<strong>main</strong>‘</span>:<br>    <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> get_lines():<br>        process(e) <span class="hljs-comment"># 处理每一行数据</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>现在要处理一个大小为10G的文件，但是内存只有4G，如果在只修改get_lines 函数而其他代码保持不变的情况下，应该如何实现？需要考虑的问题都有那些？</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">get_lines</span><span            class="hljs-params">()</span>:</span><br>    <span class="hljs-keyword">with</span> open(<span class="hljs-string">'file.txt'</span>,<span class="hljs-string">'rb'</span>) <span                class="hljs-keyword">as</span> f:<br>        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> f:<br>            <span class="hljs-keyword">yield</span> i<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>Pandaaaa906提供的方法</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">from</span> mmap <span            class="hljs-keyword">import</span> mmap</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_lines</span><span        class="hljs-params">(fp)</span>:</span><br>    <span class="hljs-keyword">with</span> open(fp,<span class="hljs-string">“r+”</span>) <span                class="hljs-keyword">as</span> f:<br>        m = mmap(f.fileno(), <span class="hljs-number">0</span>)<br>        tmp = <span class="hljs-number">0</span><br>        <span class="hljs-keyword">for</span> i, char <span class="hljs-keyword">in</span> enumerate(m):<br>            <span class="hljs-keyword">if</span> char==<span class="hljs-string">b”\n”</span>:<br>                <span class="hljs-keyword">yield</span> m[tmp:i+<span class="hljs-number">1</span>].decode()<br>                tmp = i+<span class="hljs-number">1</span></p><p><span class="hljs-keyword">if</span> <strong>name</strong>==<span class="hljs-string">“<strong>main</strong>“</span>:<br>    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> get_lines(<span class="hljs-string">“fp_some_huge_file”</span>):<br>        print(i)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>要考虑的问题有：内存只有4G无法一次性读入10G文件，需要分批读入分批读入数据要记录每次读入数据的位置。分批每次读取数据的大小，太小会在读取操作花费过多时间。<br>        <a target="_blank"           href="https://stackoverflow.com/questions/30294146/python-fastest-way-to-process-large-file"           rel="nofollow noopener noreferrer">stackoverflow.com/questions/3…</a></p><br>    <h2 class="heading" data-id="heading-33">24 补充缺失的代码</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">print_directory_contents</span><span            class="hljs-params">(sPath)</span>:</span><br><span class="hljs-string">"""<br>这个函数接收文件夹的名称作为输入参数<br>返回该文件夹中文件的路径<br>以及其包含文件夹中文件的路径<br>"""</span><br><span class="hljs-keyword">import</span> os<br><span class="hljs-keyword">for</span> s_child <span class="hljs-keyword">in</span> os.listdir(s_path):<br>    s_child_path = os.path.join(s_path, s_child)<br>    <span class="hljs-keyword">if</span> os.path.isdir(s_child_path):<br>        print_directory_contents(s_child_path)<br>    <span class="hljs-keyword">else</span>:<br>        print(s_child_path)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-34">25 输入日期， 判断这一天是这一年的第几天？</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">import</span> datetime<br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">dayofyear</span><span        class="hljs-params">()</span>:</span><br>    year = input(<span class="hljs-string">"请输入年份: "</span>)<br>    month = input(<span class="hljs-string">"请输入月份: "</span>)<br>    day = input(<span class="hljs-string">"请输入天: "</span>)<br>    date1 = datetime.date(year=int(year),month=int(month),day=int(day))<br>    date2 = datetime.date(year=int(year),month=<span class="hljs-number">1</span>,day=<span class="hljs-number">1</span>)<br>    <span class="hljs-keyword">return</span> (date1-date2).days+<span class="hljs-number">1</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-35">26 打乱一个排好序的list对象alist？</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">import</span> random<br>alist = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span                class="hljs-number">4</span>,<span class="hljs-number">5</span>]<br>random.shuffle(alist)<br>print(alist)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-36">27 现有字典 d= {‘a’:24,’g’:52,’i’:12,’k’:33}请按value值进行排序?</h2><br>    <pre><code class="hljs python copyable" lang="python">sorted(d.items(),key=<span            class="hljs-keyword">lambda</span> x:x[<span class="hljs-number">1</span>])<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-37">28 字典推导式</h2><br>    <pre><code class="hljs python copyable" lang="python">d = &#123;key:value <span class="hljs-keyword">for</span> (key,value) <span            class="hljs-keyword">in</span> iterable&#125;<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-38">29 请反转字符串 “aStr”?</h2><br>    <pre><code class="hljs python copyable" lang="python">print(<span class="hljs-string">"aStr"</span>[::<span            class="hljs-number">-1</span>])<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-39">30 将字符串 “k:1 |k1:2|k2:3|k3:4”，处理成字典 {k:1,k1:2,</h2><br>    <pre><code class="hljs python copyable" lang="python">str1 = <span            class="hljs-string">"k:1|k1:2|k2:3|k3:4"</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">str2dict</span><span        class="hljs-params">(str1)</span>:</span><br>    dict1 = &#123;&#125;<br>    <span class="hljs-keyword">for</span> iterms <span class="hljs-keyword">in</span> str1.split(<span                class="hljs-string">'|'</span>):<br>        key,value = iterms.split(<span class="hljs-string">':'</span>)<br>        dict1[key] = value<br>    <span class="hljs-keyword">return</span> dict1<br><span class="hljs-comment">#字典推导式</span><br>d = &#123;k:int(v) <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> str1.split(<span                class="hljs-string">"|"</span>) <span class="hljs-keyword">for</span> k, v <span                class="hljs-keyword">in</span> (t.split(<span class="hljs-string">":"</span>), )&#125;<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-40">31 请按alist中元素的age由大到小排序</h2><br>    <pre><code class="hljs python copyable" lang="python">alist = [&#123;<span class="hljs-string">'name'</span>:<span            class="hljs-string">'a'</span>,<span class="hljs-string">'age'</span>:<span            class="hljs-number">20</span>&#125;,&#123;<span class="hljs-string">'name'</span>:<span            class="hljs-string">'b'</span>,<span class="hljs-string">'age'</span>:<span            class="hljs-number">30</span>&#125;,&#123;<span class="hljs-string">'name'</span>:<span            class="hljs-string">'c'</span>,<span class="hljs-string">'age'</span>:<span            class="hljs-number">25</span>&#125;]<br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sort_by_age</span><span        class="hljs-params">(list1)</span>:</span><br>    <span class="hljs-keyword">return</span> sorted(alist,key=<span class="hljs-keyword">lambda</span> x:x[<span                class="hljs-string">'age'</span>],reverse=<span class="hljs-keyword">True</span>)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-41">32 下面代码的输出结果将是什么？</h2><br>    <pre><code class="hljs python copyable" lang="python">list = [<span class="hljs-string">'a'</span>,<span            class="hljs-string">'b'</span>,<span class="hljs-string">'c'</span>,<span            class="hljs-string">'d'</span>,<span            class="hljs-string">'e'</span>]<br>print(list[<span class="hljs-number">10</span>:])<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p><br>        代码将输出[],不会产生IndexError错误，就像所期望的那样，尝试用超出成员的个数的index来获取某个列表的成员。例如，尝试获取list[10]和之后的成员，会导致IndexError。然而，尝试获取列表的切片，开始的index超过了成员个数不会产生IndexError，而是仅仅返回一个空列表。这成为特别让人恶心的疑难杂症，因为运行的时候没有错误产生，导致Bug很难被追踪到。</p><br>    <h2 class="heading" data-id="heading-42">33 写一个列表生成式，产生一个公差为11的等差数列</h2><br>    <pre><code class="hljs python copyable" lang="python">print([x*<span class="hljs-number">11</span> <span            class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span            class="hljs-number">10</span>)])<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-43">34 给定两个列表，怎么找出他们相同的元素和不同的元素？</h2><br>    <pre><code class="hljs python copyable" lang="python">list1 = [<span class="hljs-number">1</span>,<span            class="hljs-number">2</span>,<span class="hljs-number">3</span>]<br>list2 = [<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>]<br>set1 = set(list1)<br>set2 = set(list2)<br>print(set1 &amp; set2)<br>print(set1 ^ set2)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-44">35 请写出一段python代码实现删除list里面的重复元素？</h2><br>    <pre><code class="hljs python copyable" lang="python">l1 = [<span class="hljs-string">'b'</span>,<span            class="hljs-string">'c'</span>,<span class="hljs-string">'d'</span>,<span            class="hljs-string">'c'</span>,<span            class="hljs-string">'a'</span>,<span class="hljs-string">'a'</span>]<br>l2 = list(set(l1))<br>print(l2)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>用list类的sort方法:</p><br>    <pre><code class="hljs python copyable" lang="python">l1 = [<span class="hljs-string">'b'</span>,<span            class="hljs-string">'c'</span>,<span class="hljs-string">'d'</span>,<span            class="hljs-string">'c'</span>,<span            class="hljs-string">'a'</span>,<span class="hljs-string">'a'</span>]<br>l2 = list(set(l1))<br>l2.sort(key=l1.index)<br>print(l2)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>也可以这样写:</p><br>    <pre><code class="hljs python copyable" lang="python">l1 = [<span class="hljs-string">'b'</span>,<span            class="hljs-string">'c'</span>,<span class="hljs-string">'d'</span>,<span            class="hljs-string">'c'</span>,<span            class="hljs-string">'a'</span>,<span class="hljs-string">'a'</span>]<br>l2 = sorted(set(l1),key=l1.index)<br>print(l2)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>也可以用遍历：</p><br>    <pre><code class="hljs python copyable" lang="python">l1 = [<span class="hljs-string">'b'</span>,<span            class="hljs-string">'c'</span>,<span class="hljs-string">'d'</span>,<span            class="hljs-string">'c'</span>,<span            class="hljs-string">'a'</span>,<span class="hljs-string">'a'</span>]<br>l2 = []<br><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> l1:<br>    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> i <span class="hljs-keyword">in</span> l2:<br>        l2.append(i)<br>print(l2)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-45">36 给定两个list A，B ,请用找出A，B中相同与不同的元素</h2><br>    <pre><code class="hljs python copyable" lang="python">A,B 中相同元素： print(set(A)&amp;set(B))<br>A,B 中不同元素:  print(set(A)^set(B))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-46">37 python新式类和经典类的区别？</h2><br>    <p>a. 在python里凡是继承了object的类，都是新式类</p><br>    <p>b. Python3里只有新式类</p><br>    <p>c. Python2里面继承object的是新式类，没有写父类的是经典类</p><br>    <p>d. 经典类目前在Python里基本没有应用</p><br>    <h2 class="heading" data-id="heading-47">38 python中内置的数据结构有几种？</h2><br>    <p>a. 整型 int、 长整型 long、浮点型 float、 复数 complex</p><br>    <p>b. 字符串 str、 列表 list、 元祖 tuple</p><br>    <p>c. 字典 dict 、 集合 set</p><br>    <p>d. Python3 中没有 long，只有无限精度的 int</p><br>    <h2 class="heading" data-id="heading-48">39 python如何实现单例模式?请写出两种实现方式?</h2><br>    <p>第一种方法:使用装饰器</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">singleton</span><span            class="hljs-params">(cls)</span>:</span><br>    instances = &#123;&#125;<br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span><span            class="hljs-params">(*args, **kwargs)</span>:</span><br>        <span class="hljs-keyword">if</span> cls <span class="hljs-keyword">not</span> <span                class="hljs-keyword">in</span> instances:<br>            instances[cls] = cls(*args, **kwargs)<br>        <span class="hljs-keyword">return</span> instances[cls]<br>    <span class="hljs-keyword">return</span> wrapper</p><p><span class="hljs-meta">@singleton</span><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span><span        class="hljs-params">(object)</span>:</span><br>    <span class="hljs-keyword">pass</span><br>foo1 = Foo()<br>foo2 = Foo()<br>print(foo1 <span class="hljs-keyword">is</span> foo2)  <span class="hljs-comment"># True</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>第二种方法：使用基类<br>        New 是真正创建实例对象的方法，所以重写基类的new 方法，以此保证创建对象的时候只生成一个实例</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span><span class="hljs-params">(object)</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title"><strong>new</strong></span><span            class="hljs-params">(cls, *args, **kwargs)</span>:</span><br>        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> hasattr(cls, <span                class="hljs-string">'_instance'</span>):<br>            cls._instance = super(Singleton, cls).<strong>new</strong>(cls, *args, **kwargs)<br>        <span class="hljs-keyword">return</span> cls._instance</p><p><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span><span        class="hljs-params">(Singleton)</span>:</span><br>    <span class="hljs-keyword">pass</span></p><p>foo1 = Foo()<br>foo2 = Foo()</p><p>print(foo1 <span class="hljs-keyword">is</span> foo2)  <span class="hljs-comment"># True</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>第三种方法：元类，元类是用于创建类对象的类，类对象创建实例对象时一定要调用call方法，因此在调用call时候保证始终只创建一个实例即可，type是python的元类</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span><span            class="hljs-params">(type)</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title"><strong>call</strong></span><span            class="hljs-params">(cls, *args, **kwargs)</span>:</span><br>        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> hasattr(cls, <span                class="hljs-string">'_instance'</span>):<br>            cls._instance = super(Singleton, cls).<strong>call</strong>(*args, **kwargs)<br>        <span class="hljs-keyword">return</span> cls._instance</p><p><span class="hljs-comment"># Python2</span><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span><span        class="hljs-params">(object)</span>:</span><br>    <strong>metaclass</strong> = Singleton</p><p><span class="hljs-comment"># Python3</span><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span><span        class="hljs-params">(metaclass=Singleton)</span>:</span><br>    <span class="hljs-keyword">pass</span></p><p>foo1 = Foo()<br>foo2 = Foo()<br>print(foo1 <span class="hljs-keyword">is</span> foo2)  <span class="hljs-comment"># True</span></p><p><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-49">40 反转一个整数，例如-123 –&gt; -321</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">Solution</span><span            class="hljs-params">(object)</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reverse</span><span            class="hljs-params">(self,x)</span>:</span><br>        <span class="hljs-keyword">if</span> <span class="hljs-number">-10</span>&lt;x&lt;<span                class="hljs-number">10</span>:<br>            <span class="hljs-keyword">return</span> x<br>        str_x = str(x)<br>        <span class="hljs-keyword">if</span> str_x[<span class="hljs-number">0</span>] !=<span                class="hljs-string">"-"</span>:<br>            str_x = str_x[::<span class="hljs-number">-1</span>]<br>            x = int(str_x)<br>        <span class="hljs-keyword">else</span>:<br>            str_x = str_x[<span class="hljs-number">1</span>:][::<span class="hljs-number">-1</span>]<br>            x = int(str_x)<br>            x = -x<br>        <span class="hljs-keyword">return</span> x <span class="hljs-keyword">if</span> <span class="hljs-number">-2147483648</span>&lt;x&lt;<span                class="hljs-number">2147483647</span> <span class="hljs-keyword">else</span> <span                class="hljs-number">0</span><br><span class="hljs-keyword">if</span> <strong>name</strong> == <span class="hljs-string">'<strong>main</strong>'</span>:<br>    s = Solution()<br>    reverse_int = s.reverse(<span class="hljs-number">-120</span>)<br>    print(reverse_int)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-50">41 设计实现遍历目录与子目录，抓取.pyc文件?</h2><br>    <p>第一种方法：</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">import</span> os</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_files</span><span        class="hljs-params">(dir,suffix)</span>:</span><br>    res = []<br>    <span class="hljs-keyword">for</span> root,dirs,files <span class="hljs-keyword">in</span> os.walk(dir):<br>        <span class="hljs-keyword">for</span> filename <span class="hljs-keyword">in</span> files:<br>            name,suf = os.path.splitext(filename)<br>            <span class="hljs-keyword">if</span> suf == suffix:<br>                res.append(os.path.join(root,filename))</p><pre><code>print(res)</code></pre><p>get_files(<span class="hljs-string">“./“</span>,<span class="hljs-string">‘.pyc’</span>)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>第二种方法：</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">import</span> os</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">pick</span><span        class="hljs-params">(obj)</span>:</span><br>    <span class="hljs-keyword">if</span> ob.endswith(<span class="hljs-string">“.pyc”</span>):<br>        print(obj)</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scan_path</span><span        class="hljs-params">(ph)</span>:</span><br>    file_list = os.listdir(ph)<br>    <span class="hljs-keyword">for</span> obj <span class="hljs-keyword">in</span> file_list:<br>        <span class="hljs-keyword">if</span> os.path.isfile(obj):<br>    pick(obj)<br>        <span class="hljs-keyword">elif</span> os.path.isdir(obj):<br>            scan_path(obj)</p><p><span class="hljs-keyword">if</span> <strong>name</strong>==<span class="hljs-string">‘<strong>main</strong>‘</span>:<br>    path = input(<span class="hljs-string">‘输入目录’</span>)<br>    scan_path(path)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>第三种方法</p><br>    <pre><code class="hljs bash copyable" lang="bash">from glob import iglob</p><p>def func(fp, postfix):<br>    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> iglob(f<span class="hljs-string">“&#123;fp&#125;/**/*&#123;postfix&#125;”</span>, recursive=True):<br>        <span class="hljs-built_in">print</span>(i)</p><p><span class="hljs-keyword">if</span> <strong>name</strong> == <span class="hljs-string">“<strong>main</strong>“</span>:<br>    postfix = <span class="hljs-string">“.pyc”</span><br>    func(<span class="hljs-string">“K:\Python_script”</span>, postfix)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-51">42 Python-遍历列表时删除元素的正确做法</h2><br>    <p>遍历在新在列表操作，删除时在原来的列表操作</p><br>    <pre><code class="hljs python copyable" lang="python">a = [<span class="hljs-number">1</span>,<span            class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span            class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span            class="hljs-number">8</span>]<br>print(id(a))<br>print(id(a[:]))<br><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> a[:]:<br>    <span class="hljs-keyword">if</span> i&gt;<span class="hljs-number">5</span>:<br>        <span class="hljs-keyword">pass</span><br>    <span class="hljs-keyword">else</span>:<br>        a.remove(i)<br>    print(a)<br>print(<span class="hljs-string">'-----------'</span>)<br>print(id(a))</p><p><span class="copy-code-btn">复制代码</span></code></pre><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-comment">#filter</span><br>a=[<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span                class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span                class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>]<br>b = filter(<span class="hljs-keyword">lambda</span> x: x&gt;<span class="hljs-number">5</span>,a)<br>print(list(b))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>列表解析</p><br>    <pre><code class="hljs python copyable" lang="python">a=[<span class="hljs-number">1</span>,<span            class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span            class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span            class="hljs-number">8</span>]<br>b = [i <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> a <span                class="hljs-keyword">if</span> i&gt;<span class="hljs-number">5</span>]<br>print(b)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>倒序删除<br>        因为列表总是‘向前移’，所以可以倒序遍历，即使后面的元素被修改了，还没有被遍历的元素和其坐标还是保持不变的</p><br>    <pre><code class="hljs python copyable" lang="python">a=[<span class="hljs-number">1</span>,<span            class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span            class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span            class="hljs-number">8</span>]<br>print(id(a))<br><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(a)<span                class="hljs-number">-1</span>,<span class="hljs-number">-1</span>,<span                class="hljs-number">-1</span>):<br>    <span class="hljs-keyword">if</span> a[i]&gt;<span class="hljs-number">5</span>:<br>        <span class="hljs-keyword">pass</span><br>    <span class="hljs-keyword">else</span>:<br>        a.remove(a[i])<br>print(id(a))<br>print(<span class="hljs-string">'-----------'</span>)<br>print(a)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-52">43 字符串的操作题目</h2><br>    <p>全字母短句 PANGRAM 是包含所有英文字母的句子，比如：A QUICK BROWN FOX JUMPS OVER THE LAZY DOG. 定义并实现一个方法 get_missing_letter,<br>        传入一个字符串采纳数，返回参数字符串变成一个 PANGRAM 中所缺失的字符。应该忽略传入字符串参数中的大小写，返回应该都是小写字符并按字母顺序排序（请忽略所有非 ACSII 字符）</p><br>    <p><strong>下面示例是用来解释，双引号不需要考虑:</strong></p><br>    <p>(0)输入: “A quick brown for jumps over the lazy dog”</p><br>    <p>返回： “”</p><br>    <p>(1)输入: “A slow yellow fox crawls under the proactive dog”</p><br>    <p>返回: “bjkmqz”</p><br>    <p>(2)输入: “Lions, and tigers, and bears, oh my!”</p><br>    <p>返回: “cfjkpquvwxz”</p><br>    <p>(3)输入: “”</p><br>    <p>返回：”abcdefghijklmnopqrstuvwxyz”</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">get_missing_letter</span><span            class="hljs-params">(a)</span>:</span><br>    s1 = set(<span class="hljs-string">"abcdefghijklmnopqrstuvwxyz"</span>)<br>    s2 = set(a)<br>    ret = <span class="hljs-string">""</span>.join(sorted(s1-s2))<br>    <span class="hljs-keyword">return</span> ret</p><p>print(get_missing_letter(<span class="hljs-string">“python”</span>))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-53">44 可变类型和不可变类型</h2><br>    <p>1,可变类型有list,dict.不可变类型有string，number,tuple.</p><br>    <p>2,当进行修改操作时，可变类型传递的是内存中的地址，也就是说，直接修改内存中的值，并没有开辟新的内存。</p><br>    <p>3,不可变类型被改变时，并没有改变原内存地址中的值，而是开辟一块新的内存，将原地址中的值复制过去，对这块新开辟的内存中的值进行操作。</p><br>    <h2 class="heading" data-id="heading-54">45 is和==有什么区别？</h2><br>    <p>is：比较的是两个对象的id值是否相等，也就是比较俩对象是否为同一个实例对象。是否指向同一个内存地址</p><br>    <p>== ： 比较的两个对象的内容/值是否相等，默认会调用对象的eq()方法</p><br>    <h2 class="heading" data-id="heading-55">46 求出列表所有奇数并构造新列表</h2><br>    <pre><code class="hljs python copyable" lang="python">a = [<span class="hljs-number">1</span>,<span            class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span            class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span            class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">10</span>]<br>res = [ i <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> a <span                class="hljs-keyword">if</span> i%<span class="hljs-number">2</span>==<span                class="hljs-number">1</span>]<br>print(res)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-56">47 用一行python代码写出1+2+3+10248</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">from</span> functools <span            class="hljs-keyword">import</span> reduce<br><span class="hljs-comment">#1.使用sum内置求和函数</span><br>num = sum([<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span                class="hljs-number">3</span>,<span class="hljs-number">10248</span>])<br>print(num)<br><span class="hljs-comment">#2.reduce 函数</span><br>num1 = reduce(<span class="hljs-keyword">lambda</span> x,y :x+y,[<span class="hljs-number">1</span>,<span                class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span                class="hljs-number">10248</span>])<br>print(num1)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-57">48 Python中变量的作用域？（变量查找顺序)</h2><br>    <p>函数作用域的LEGB顺序</p><br>    <p>1.什么是LEGB?</p><br>    <p>L： local 函数内部作用域</p><br>    <p>E: enclosing 函数内部与内嵌函数之间</p><br>    <p>G: global 全局作用域</p><br>    <p>B： build-in 内置作用</p><br>    <p>python在函数里面的查找分为4种，称之为LEGB，也正是按照这是顺序来查找的</p><br>    <h2 class="heading" data-id="heading-58">49 字符串 <code>"123"</code> 转换成 <code>123</code>，不使用内置api，例如<br>        <code>int()</code></h2><br>    <p>方法一： 利用 <code>str</code> 函数</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">atoi</span><span            class="hljs-params">(s)</span>:</span><br>    num = <span class="hljs-number">0</span><br>    <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> s:<br>        <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(<span                class="hljs-number">10</span>):<br>            <span class="hljs-keyword">if</span> v == str(j):<br>                num = num * <span class="hljs-number">10</span> + j<br>    <span class="hljs-keyword">return</span> num<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>方法二： 利用 <code>ord</code> 函数</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">atoi</span><span            class="hljs-params">(s)</span>:</span><br>    num = <span class="hljs-number">0</span><br>    <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> s:<br>        num = num * <span class="hljs-number">10</span> + ord(v) - ord(<span class="hljs-string">'0'</span>)<br>    <span class="hljs-keyword">return</span> num<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>方法三: 利用 <code>eval</code> 函数</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">atoi</span><span            class="hljs-params">(s)</span>:</span><br>    num = <span class="hljs-number">0</span><br>    <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> s:<br>        t = <span class="hljs-string">"%s * 1"</span> % v<br>        n = eval(t)<br>        num = num * <span class="hljs-number">10</span> + n<br>    <span class="hljs-keyword">return</span> num<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>方法四: 结合方法二，使用 <code>reduce</code>，一行解决</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">from</span> functools <span            class="hljs-keyword">import</span> reduce<br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">atoi</span><span        class="hljs-params">(s)</span>:</span><br>    <span class="hljs-keyword">return</span> reduce(<span class="hljs-keyword">lambda</span> num, v: num * <span                class="hljs-number">10</span> + ord(v) - ord(<span class="hljs-string">'0'</span>), s, <span                class="hljs-number">0</span>)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-59">50 Given an array of integers</h2><br>    <p>给定一个整数数组和一个目标值，找出数组中和为目标值的两个数。你可以假设每个输入只对应一种答案，且同样的元素不能被重复利用。示例:给定nums = [2,7,11,15],target=9 因为<br>        nums[0]+nums[1] = 2+7 =9,所以返回[0,1]</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">twoSum</span><span            class="hljs-params">(self,nums,target)</span>:</span><br>        <span class="hljs-string">"""<br>        :type nums: List[int]<br>        :type target: int<br>        :rtype: List[int]<br>        """</span><br>        d = &#123;&#125;<br>        size = <span class="hljs-number">0</span><br>        <span class="hljs-keyword">while</span> size &lt; len(nums):<br>            <span class="hljs-keyword">if</span> target-nums[size] <span class="hljs-keyword">in</span> d:<br>                <span class="hljs-keyword">if</span> d[target-nums[size]] &lt;size:<br>                    <span class="hljs-keyword">return</span> [d[target-nums[size]],size]<br>                <span class="hljs-keyword">else</span>:<br>                    d[nums[size]] = size<br>                size = size +<span class="hljs-number">1</span><br>solution = Solution()<br>list = [<span class="hljs-number">2</span>,<span class="hljs-number">7</span>,<span class="hljs-number">11</span>,<span                class="hljs-number">15</span>]<br>target = <span class="hljs-number">9</span><br>nums = solution.twoSum(list,target)<br>print(nums)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p><br>        给列表中的字典排序：假设有如下list对象，alist=[{“name”:”a”,”age”:20},{“name”:”b”,”age”:30},{“name”:”c”,”age”:25}],将alist中的元素按照age从大到小排序<br>        alist=[{“name”:”a”,”age”:20},{“name”:”b”,”age”:30},{“name”:”c”,”age”:25}]</p><br>    <pre><code class="hljs python copyable" lang="python">alist_sort = sorted(alist,key=<span class="hljs-keyword">lambda</span> e: e.<strong>getitem</strong>(<span            class="hljs-string">'age'</span>),reverse=<span class="hljs-keyword">True</span>)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-60">51 python代码实现删除一个list里面的重复元素</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">distFunc1</span><span            class="hljs-params">(a)</span>:</span><br>    <span class="hljs-string">"""使用集合去重"""</span><br>    a = list(set(a))<br>    print(a)</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">distFunc2</span><span        class="hljs-params">(a)</span>:</span><br>    <span class="hljs-string">“””将一个列表的数据取出放到另一个列表中，中间作判断”””</span><br>    list = []<br>    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> a:<br>        <span class="hljs-keyword">if</span> i <span class="hljs-keyword">not</span> <span                class="hljs-keyword">in</span> list:<br>            list.append(i)<br>    <span class="hljs-comment">#如果需要排序的话用sort</span><br>    list.sort()<br>    print(list)</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">distFunc3</span><span        class="hljs-params">(a)</span>:</span><br>    <span class="hljs-string">“””使用字典”””</span><br>    b = &#123;&#125;<br>    b = b.fromkeys(a)<br>    c = list(b.keys())<br>    print(c)</p><p><span class="hljs-keyword">if</span> <strong>name</strong> == <span class="hljs-string">“<strong>main</strong>“</span>:<br>    a = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">4</span>,<span                class="hljs-number">2</span>,<span class="hljs-number">4</span>,<span                class="hljs-number">5</span>,<span class="hljs-number">7</span>,<span                class="hljs-number">10</span>,<span                class="hljs-number">5</span>,<span class="hljs-number">5</span>,<span                class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span                class="hljs-number">9</span>,<span class="hljs-number">0</span>,<span class="hljs-number">3</span>]<br>    distFunc1(a)<br>    distFunc2(a)<br>    distFunc3(a)</p><p><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-61">52 统计一个文本中单词频次最高的10个单词？</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">import</span> re</p><p><span class="hljs-comment"># 方法一</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test</span><span        class="hljs-params">(filepath)</span>:</span></p><pre><code>distone = &#123;&#125;&lt;span class=&quot;hljs-keyword&quot;&gt;with&lt;/span&gt; open(filepath) &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; f:    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; line &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; f:        line = re.sub(&lt;span class=&quot;hljs-string&quot;&gt;&quot;\W+&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot; &quot;&lt;/span&gt;, line)        lineone = line.split()        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; keyone &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; lineone:            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; distone.get(keyone):                distone[keyone] = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;            &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:                distone[keyone] += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;num_ten = sorted(distone.items(), key=&lt;span class=&quot;hljs-keyword&quot;&gt;lambda&lt;/span&gt; x:x[&lt;span            class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;], reverse=&lt;span class=&quot;hljs-keyword&quot;&gt;True&lt;/span&gt;)[:&lt;span            class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;]num_ten =[x[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;] &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; num_ten]&lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; num_ten</code></pre><p><span class="hljs-comment"># 方法二 </span><br><span class="hljs-comment"># 使用 built-in 的 Counter 里面的 most_common</span><br><span class="hljs-keyword">import</span> re<br><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> Counter</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test2</span><span        class="hljs-params">(filepath)</span>:</span><br>    <span class="hljs-keyword">with</span> open(filepath) <span class="hljs-keyword">as</span> f:<br>        <span class="hljs-keyword">return</span> list(map(<span class="hljs-keyword">lambda</span> c: c[<span                class="hljs-number">0</span>], Counter(re.sub(<span class="hljs-string">“\W+”</span>, <span                class="hljs-string">“ “</span>, f.read()).split()).most_common(<span class="hljs-number">10</span>)))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-62">53 请写出一个函数满足以下条件</h2><br>    <p>该函数的输入是一个仅包含数字的list,输出一个新的list，其中每一个元素要满足以下条件：</p><br>    <p>1、该元素是偶数</p><br>    <p>2、该元素在原list中是在偶数的位置(index是偶数)</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">num_list</span><span            class="hljs-params">(num)</span>:</span><br>    <span class="hljs-keyword">return</span> [i <span class="hljs-keyword">for</span> i <span                class="hljs-keyword">in</span> num <span class="hljs-keyword">if</span> i %<span                class="hljs-number">2</span> ==<span class="hljs-number">0</span> <span                class="hljs-keyword">and</span> num.index(i)%<span class="hljs-number">2</span>==<span                class="hljs-number">0</span>]</p><p>num = [<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span                class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span                class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span                class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span                class="hljs-number">9</span>,<span class="hljs-number">10</span>]<br>result = num_list(num)<br>print(result)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-63">54 使用单一的列表生成式来产生一个新的列表</h2><br>    <p>该列表只包含满足以下条件的值，元素为原始列表中偶数切片</p><br>    <pre><code class="hljs python copyable" lang="python">list_data = [<span class="hljs-number">1</span>,<span            class="hljs-number">2</span>,<span class="hljs-number">5</span>,<span class="hljs-number">8</span>,<span            class="hljs-number">10</span>,<span class="hljs-number">3</span>,<span            class="hljs-number">18</span>,<span class="hljs-number">6</span>,<span class="hljs-number">20</span>]<br>res = [x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> list_data[::<span                class="hljs-number">2</span>] <span class="hljs-keyword">if</span> x %<span                class="hljs-number">2</span> ==<span class="hljs-number">0</span>]<br>print(res)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-64">55 用一行代码生成[1,4,9,16,25,36,49,64,81,100]</h2><br>    <pre><code class="hljs python copyable" lang="python">[x * x <span class="hljs-keyword">for</span> x <span            class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>,<span            class="hljs-number">11</span>)]<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-65">56 输入某年某月某日，判断这一天是这一年的第几天？</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">import</span> datetime</p><p>y = int(input(<span class="hljs-string">“请输入4位数字的年份:”</span>))<br>m = int(input(<span class="hljs-string">“请输入月份:”</span>))<br>d = int(input(<span class="hljs-string">“请输入是哪一天”</span>))</p><p>targetDay = datetime.date(y,m,d)<br>dayCount = targetDay - datetime.date(targetDay.year <span class="hljs-number">-1</span>,<span                class="hljs-number">12</span>,<span class="hljs-number">31</span>)<br>print(<span class="hljs-string">“%s是 %s年的第%s天。”</span>%(targetDay,y,dayCount.days))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-66">57 两个有序列表，l1,l2，对这两个列表进行合并不可使用extend</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">loop_merge_sort</span><span            class="hljs-params">(l1,l2)</span>:</span><br>    tmp = []<br>    <span class="hljs-keyword">while</span> len(l1)&gt;<span class="hljs-number">0</span> <span                class="hljs-keyword">and</span> len(l2)&gt;<span class="hljs-number">0</span>:<br>        <span class="hljs-keyword">if</span> l1[<span class="hljs-number">0</span>] &lt;l2[<span                class="hljs-number">0</span>]:<br>            tmp.append(l1[<span class="hljs-number">0</span>])<br>            <span class="hljs-keyword">del</span> l1[<span class="hljs-number">0</span>]<br>        <span class="hljs-keyword">else</span>:<br>            tmp.append(l2[<span class="hljs-number">0</span>])<br>            <span class="hljs-keyword">del</span> l2[<span class="hljs-number">0</span>]<br>    <span class="hljs-keyword">while</span> len(l1)&gt;<span class="hljs-number">0</span>:<br>        tmp.append(l1[<span class="hljs-number">0</span>])<br>        <span class="hljs-keyword">del</span> l1[<span class="hljs-number">0</span>]<br>    <span class="hljs-keyword">while</span> len(l2)&gt;<span class="hljs-number">0</span>:<br>        tmp.append(l2[<span class="hljs-number">0</span>])<br>        <span class="hljs-keyword">del</span> l2[<span class="hljs-number">0</span>]<br>    <span class="hljs-keyword">return</span> tmp<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-67">58 给定一个任意长度数组，实现一个函数</h2><br>    <p>让所有奇数都在偶数前面，而且奇数升序排列，偶数降序排序，如字符串’1982376455’,变成’1355798642’</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-comment"># 方法一</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func1</span><span        class="hljs-params">(l)</span>:</span><br>    <span class="hljs-keyword">if</span> isinstance(l, str):<br>        l = [int(i) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> l]<br>    l.sort(reverse=<span class="hljs-keyword">True</span>)<br>    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(l)):<br>        <span class="hljs-keyword">if</span> l[i] % <span class="hljs-number">2</span> &gt; <span                class="hljs-number">0</span>:<br>            l.insert(<span class="hljs-number">0</span>, l.pop(i))<br>    print(<span class="hljs-string">''</span>.join(str(e) <span class="hljs-keyword">for</span> e <span                class="hljs-keyword">in</span> l))</p><p><span class="hljs-comment"># 方法二</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func2</span><span        class="hljs-params">(l)</span>:</span><br>    print(<span class="hljs-string">“”</span>.join(sorted(l, key=<span                class="hljs-keyword">lambda</span> x: int(x) % <span class="hljs-number">2</span> == <span                class="hljs-number">0</span> <span class="hljs-keyword">and</span> <span                class="hljs-number">20</span> - int(x) <span class="hljs-keyword">or</span> int(x))))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-68">59 写一个函数找出一个整数数组中，第二大的数</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">find_second_large_num</span><span            class="hljs-params">(num_list)</span>:</span><br>    <span class="hljs-string">"""<br>    找出数组第2大的数字<br>    """</span><br>    <span class="hljs-comment"># 方法一</span><br>    <span class="hljs-comment"># 直接排序，输出倒数第二个数即可</span><br>    tmp_list = sorted(num_list)<br>    print(<span class="hljs-string">"方法一\nSecond_large_num is :"</span>, tmp_list[<span class="hljs-number">-2</span>])</p><pre><code>&lt;span class=&quot;hljs-comment&quot;&gt;# 方法二&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 设置两个标志位一个存储最大数一个存储次大数&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# two 存储次大值，one 存储最大值，遍历一次数组即可，先判断是否大于 one，若大于将 one 的值给 two，将 num_list[i] 的值给 one，否则比较是否大于two，若大于直接将 num_list[i] 的值给two，否则pass&lt;/span&gt;one = num_list[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]two = num_list[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; range(&lt;span            class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, len(num_list)):    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; num_list[i] &amp;gt; one:        two = one        one = num_list[i]    &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; num_list[i] &amp;gt; two:        two = num_list[i]print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;方法二\nSecond_large_num is :&quot;&lt;/span&gt;, two)&lt;span class=&quot;hljs-comment&quot;&gt;# 方法三&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 用 reduce 与逻辑符号 (and, or)&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 基本思路与方法二一样，但是不需要用 if 进行判断。&lt;/span&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;from&lt;/span&gt; functools &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; reducenum = reduce(&lt;span class=&quot;hljs-keyword&quot;&gt;lambda&lt;/span&gt; ot, x: ot[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] &amp;lt; x &lt;span            class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; (ot[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;], x) &lt;span            class=&quot;hljs-keyword&quot;&gt;or&lt;/span&gt; ot[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;] &amp;lt; x &lt;span            class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; (x, ot[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]) &lt;span            class=&quot;hljs-keyword&quot;&gt;or&lt;/span&gt; ot, num_list, (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span            class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;))[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;方法三\nSecond_large_num is :&quot;&lt;/span&gt;, num)</code></pre><p><span class="hljs-keyword">if</span> <strong>name</strong> == <span class="hljs-string">‘<strong>main</strong>_’</span>:<br>    num_list = [<span class="hljs-number">34</span>, <span class="hljs-number">11</span>, <span                class="hljs-number">23</span>, <span class="hljs-number">56</span>, <span                class="hljs-number">78</span>, <span class="hljs-number">0</span>, <span                class="hljs-number">9</span>, <span class="hljs-number">12</span>, <span                class="hljs-number">3</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>]<br>    find_second_large_num(num_list)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-69">60 阅读一下代码他们的输出结果是什么？</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">multi</span><span            class="hljs-params">()</span>:</span><br>    <span class="hljs-keyword">return</span> [<span class="hljs-keyword">lambda</span> x : i*x <span                class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span                class="hljs-number">4</span>)]<br>print([m(<span class="hljs-number">3</span>) <span class="hljs-keyword">for</span> m <span                class="hljs-keyword">in</span> multi()])<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>正确答案是[9,9,9,9]，而不是[0,3,6,9]产生的原因是Python的闭包的后期绑定导致的，这意味着在闭包中的变量是在内部函数被调用的时候被查找的，因为，最后函数被调用的时候，for循环已经完成, i<br>        的值最后是3,因此每一个返回值的i都是3,所以最后的结果是[9,9,9,9]</p><br>    <h2 class="heading" data-id="heading-70">61 统计一段字符串中字符出现的次数</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-comment"># 方法一</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">count_str</span><span        class="hljs-params">(str_data)</span>:</span><br>    <span class="hljs-string">"""定义一个字符出现次数的函数"""</span><br>    dict_str = &#123;&#125;<br>    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> str_data:<br>        dict_str[i] = dict_str.get(i, <span class="hljs-number">0</span>) + <span class="hljs-number">1</span><br>    <span class="hljs-keyword">return</span> dict_str<br>dict_str = count_str(<span class="hljs-string">"AAABBCCAC"</span>)<br>str_count_data = <span class="hljs-string">""</span><br><span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> dict_str.items():<br>    str_count_data += k + str(v)<br>print(str_count_data)</p><p><span class="hljs-comment"># 方法二</span><br><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> Counter</p><p>print(<span class="hljs-string">“”</span>.join(map(<span class="hljs-keyword">lambda</span> x: x[<span                class="hljs-number">0</span>] + str(x[<span class="hljs-number">1</span>]), Counter(<span                class="hljs-string">“AAABBCCAC”</span>).most_common())))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-71">62 Python中类方法、类实例方法、静态方法有何区别？</h2><br>    <p>类方法: 是类对象的方法，在定义时需要在上方使用 @classmethod 进行装饰,形参为cls，表示类对象，类对象和实例对象都可调用</p><br>    <p>类实例方法: 是类实例化对象的方法,只有实例对象可以调用，形参为self,指代对象本身;</p><br>    <p>静态方法: 是一个任意函数，在其上方使用 @staticmethod 进行装饰，可以用对象直接调用，静态方法实际上跟该类没有太大关系</p><br>    <h2 class="heading" data-id="heading-72">63 遍历一个object的所有属性，并print每一个属性名？</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">Car</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title"><strong>init</strong></span><span            class="hljs-params">(self,name,loss)</span>:</span> <span class="hljs-comment"># loss [价格，油耗，公里数]</span><br>        self.name = name<br>        self.loss = loss</p><pre><code>&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;getName&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; self.name&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;getPrice&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;# 获取汽车价格&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; self.loss[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;getLoss&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;# 获取汽车损耗值&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; self.loss[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] * self.loss[&lt;span            class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;]</code></pre><p>Bmw = Car(<span class="hljs-string">“宝马”</span>,[<span class="hljs-number">60</span>,<span class="hljs-number">9</span>,<span                class="hljs-number">500</span>]) <span class="hljs-comment"># 实例化一个宝马车对象</span><br>print(getattr(Bmw,<span class="hljs-string">“name”</span>)) <span class="hljs-comment"># 使用getattr()传入对象名字,属性值。</span><br>print(dir(Bmw)) <span class="hljs-comment"># 获Bmw所有的属性和方法</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-73">64 写一个类，并让它尽可能多的支持操作符?</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">Array</span>:</span><br>    __list = []</p><pre><code>&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__init__&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;constructor&quot;&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__del__&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;destruct&quot;&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__str__&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;this self-defined array class&quot;&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__getitem__&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self,key)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; self.__list[key]&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__len__&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; len(self.__list)&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Add&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self,value)&lt;/span&gt;:&lt;/span&gt;    self.__list.append(value)&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Remove&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self,index)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;del&lt;/span&gt; self.__list[index]&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;DisplayItems&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;show all items---&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; self.__list:        &lt;span class=&quot;hljs-keyword&quot;&gt;print&lt;/span&gt; item    </code></pre><p><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-74">65 关于Python内存管理,下列说法错误的是 B</h2><br>    <p>A,变量不必事先声明 B,变量无须先创建和赋值而直接使用</p><br>    <p>C,变量无须指定类型 D,可以使用del释放资源</p><br>    <h2 class="heading" data-id="heading-75">66 Python的内存管理机制及调优手段？</h2><br>    <p>内存管理机制: 引用计数、垃圾回收、内存池</p><br>    <p>引用计数：引用计数是一种非常高效的内存管理手段，当一个Python对象被引用时其引用计数增加1,</p><br>    <p>当其不再被一个变量引用时则计数减1,当引用计数等于0时对象被删除。弱引用不会增加引用计数</p><br>    <p>垃圾回收：</p><br>    <p>1.引用计数</p><br>    <p><br>        引用计数也是一种垃圾收集机制，而且也是一种最直观、最简单的垃圾收集技术。当Python的某个对象的引用计数降为0时，说明没有任何引用指向该对象，该对象就成为要被回收的垃圾了。比如某个新建对象，它被分配给某个引用，对象的引用计数变为1，如果引用被删除，对象的引用计数为0,那么该对象就可以被垃圾回收。不过如果出现循环引用的话，引用计数机制就不再起有效的作用了。</p><br>    <p>2.标记清除</p><br>    <p>调优手段</p><br>    <p>1.手动垃圾回收</p><br>    <p>2.调高垃圾回收阈值</p><br>    <p>3.避免循环引用</p><br>    <h2 class="heading" data-id="heading-76">67 内存泄露是什么？如何避免？</h2><br>    <p><strong>内存泄漏</strong>指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失，而是应用程序分配某段内存后，由于设计错误，导致在释放该段内存之前就失去了对该段内存的控制，从而造成了内存的浪费。<br>    </p><br>    <p>有<code><strong>del</strong>()</code>函数的对象间的循环引用是导致内存泄露的主凶。不使用一个对象时使用: del object 来删除一个对象的引用计数就可以有效防止内存泄露问题。</p><br>    <p>通过Python扩展模块gc 来查看不能回收的对象的详细信息。</p><br>    <p>可以通过 sys.getrefcount(obj) 来获取对象的引用计数，并根据返回值是否为0来判断是否内存泄露</p><br>    <h2 class="heading" data-id="heading-77">68 python常见的列表推导式？</h2><br>    <p>[表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件]</p><br>    <h2 class="heading" data-id="heading-78">69 简述read、readline、readlines的区别？</h2><br>    <p>read 读取整个文件</p><br>    <p>readline 读取下一行</p><br>    <p>readlines 读取整个文件到一个迭代器以供我们遍历</p><br>    <h2 class="heading" data-id="heading-79">70 什么是Hash（散列函数）？</h2><br>    <p><strong>散列函数</strong>（英语：Hash function）又称<strong>散列算法</strong>、<strong>哈希函数</strong>，是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要，使得数据量变小，将数据的格式固定下来。该函数将数据打乱混合，重新创建一个叫做<strong>散列值</strong>（hash<br>        values，hash codes，hash sums，或hashes）的指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表</p><br>    <h2 class="heading" data-id="heading-80">71 python函数重载机制？</h2><br>    <p>函数重载主要是为了解决两个问题。<br>        1。可变参数类型。<br>        2。可变参数个数。</p><br>    <p>另外，一个基本的设计原则是，仅仅当两个函数除了参数类型和参数个数不同以外，其功能是完全相同的，此时才使用函数重载，如果两个函数的功能其实不同，那么不应当使用重载，而应当使用一个名字不同的函数。</p><br>    <p>好吧，那么对于情况 1 ，函数功能相同，但是参数类型不同，python 如何处理？答案是根本不需要处理，因为 python 可以接受任何类型的参数，如果函数的功能相同，那么不同的参数类型在 python<br>        中很可能是相同的代码，没有必要做成两个不同函数。</p><br>    <p>那么对于情况 2 ，函数功能相同，但参数个数不同，python 如何处理？大家知道，答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同，那么那些缺少的参数终归是需要用的。</p><br>    <p>好了，鉴于情况 1 跟 情况 2 都有了解决方案，python 自然就不需要函数重载了。</p><br>    <h2 class="heading" data-id="heading-81">72 手写一个判断时间的装饰器</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">import</span> datetime</p><p><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TimeException</span><span        class="hljs-params">(Exception)</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title"><strong>init</strong></span><span            class="hljs-params">(self, exception_info)</span>:</span><br>        super().<strong>init</strong>()<br>        self.info = exception_info</p><pre><code>&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__str__&lt;/span&gt;&lt;span        class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; self.info</code></pre><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">timecheck</span><span        class="hljs-params">(func)</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span><span            class="hljs-params">(*args, **kwargs)</span>:</span><br>        <span class="hljs-keyword">if</span> datetime.datetime.now().year == <span class="hljs-number">2019</span>:<br>            func(*args, **kwargs)<br>        <span class="hljs-keyword">else</span>:<br>            <span class="hljs-keyword">raise</span> TimeException(<span class="hljs-string">“函数已过时”</span>)</p><pre><code>&lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; wrapper</code></pre><p><span class="hljs-meta">@timecheck</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test</span><span        class="hljs-params">(name)</span>:</span><br>    print(<span class="hljs-string">“Hello {}, 2019 Happy”</span>.format(name))</p><p><span class="hljs-keyword">if</span> <strong>name</strong> == <span class="hljs-string">“<strong>main</strong>“</span>:<br>    test(<span class="hljs-string">“backbp”</span>)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-82">73 使用Python内置的filter()方法来过滤？</h2><br>    <pre><code class="hljs python copyable" lang="python">list(filter(<span            class="hljs-keyword">lambda</span> x: x % <span            class="hljs-number">2</span> == <span class="hljs-number">0</span>, range(<span            class="hljs-number">10</span>)))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-83">74 编写函数的4个原则</h2><br>    <p>1.函数设计要尽量短小</p><br>    <p>2.函数声明要做到合理、简单、易于使用</p><br>    <p>3.函数参数设计应该考虑向下兼容</p><br>    <p>4.一个函数只做一件事情，尽量保证函数语句粒度的一致性</p><br>    <h2 class="heading" data-id="heading-84">75 函数调用参数的传递方式是值传递还是引用传递？</h2><br>    <p>Python的参数传递有：位置参数、默认参数、可变参数、关键字参数。</p><br>    <p>函数的传值到底是值传递还是引用传递、要分情况：</p><br>    <p>不可变参数用值传递：像整数和字符串这样的不可变对象，是通过拷贝进行传递的，因为你无论如何都不可能在原处改变不可变对象。</p><br>    <p>可变参数是引用传递：比如像列表，字典这样的对象是通过引用传递、和C语言里面的用指针传递数组很相似，可变对象能在函数内部改变。</p><br>    <h2 class="heading" data-id="heading-85">76 如何在function里面设置一个全局变量</h2><br>    <pre><code class="hljs python copyable" lang="python">globals() <span            class="hljs-comment"># 返回包含当前作用余全局变量的字典。</span><br><span class="hljs-keyword">global</span> 变量 设置使用全局变量<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-86">77 对缺省参数的理解 ？</h2><br>    <p>缺省参数指在调用函数的时候没有传入参数的情况下，调用默认的参数，在调用函数的同时赋值时，所传入的参数会替代默认参数。</p><br>    <p>*args是不定长参数，它可以表示输入参数是不确定的，可以是任意多个。</p><br>    <p>**kwargs是关键字参数，赋值的时候是以键值对的方式，参数可以是任意多对在定义函数的时候</p><br>    <p>不确定会有多少参数会传入时，就可以使用两个参数</p><br>    <h2 class="heading" data-id="heading-87">78 带参数的装饰器?</h2><br>    <p>带定长参数的装饰器</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">new_func</span><span            class="hljs-params">(func)</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrappedfun</span><span            class="hljs-params">(username, passwd)</span>:</span><br>        <span class="hljs-keyword">if</span> username == <span class="hljs-string">'root'</span> <span                class="hljs-keyword">and</span> passwd == <span class="hljs-string">'123456789'</span>:<br>            print(<span class="hljs-string">'通过认证'</span>)<br>            print(<span class="hljs-string">'开始执行附加功能'</span>)<br>            <span class="hljs-keyword">return</span> func()<br>           <span class="hljs-keyword">else</span>:<br>            print(<span class="hljs-string">'用户名或密码错误'</span>)<br>            <span class="hljs-keyword">return</span><br>    <span class="hljs-keyword">return</span> wrappedfun</p><p><span class="hljs-meta">@new_func</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">origin</span><span        class="hljs-params">()</span>:</span><br>    print(<span class="hljs-string">‘开始执行函数’</span>)<br>origin(<span class="hljs-string">‘root’</span>,<span class="hljs-string">‘123456789’</span>)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>带不定长参数的装饰器</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-function"><span            class="hljs-keyword">def</span> <span class="hljs-title">new_func</span><span            class="hljs-params">(func)</span>:</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrappedfun</span><span            class="hljs-params">(*parts)</span>:</span><br>        <span class="hljs-keyword">if</span> parts:<br>            counts = len(parts)<br>            print(<span class="hljs-string">'本系统包含 '</span>, end=<span class="hljs-string">''</span>)<br>            <span class="hljs-keyword">for</span> part <span class="hljs-keyword">in</span> parts:<br>                print(part, <span class="hljs-string">' '</span>,end=<span class="hljs-string">''</span>)<br>            print(<span class="hljs-string">'等'</span>, counts, <span class="hljs-string">'部分'</span>)<br>            <span class="hljs-keyword">return</span> func()<br>        <span class="hljs-keyword">else</span>:<br>            print(<span class="hljs-string">'用户名或密码错误'</span>)<br>            <span class="hljs-keyword">return</span> func()<br>   <span class="hljs-keyword">return</span> wrappedfun</p><p><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-88">79 为什么函数名字可以当做参数用?</h2><br>    <p>Python中一切皆对象，函数名是函数在内存中的空间，也是一个对象</p><br>    <h2 class="heading" data-id="heading-89">80 Python中pass语句的作用是什么？</h2><br>    <p>在编写代码时只写框架思路，具体实现还未编写就可以用pass进行占位，是程序不报错，不会进行任何操作。</p><br>    <h2 class="heading" data-id="heading-90">81 有这样一段代码，print c会输出什么，为什么？</h2><br>    <pre><code class="hljs python copyable" lang="python">a = <span class="hljs-number">10</span><br>b = <span class="hljs-number">20</span><br>c = [a]<br>a = <span class="hljs-number">15</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>答：10对于字符串，数字，传递是相应的值</p><br>    <h2 class="heading" data-id="heading-91">82 交换两个变量的值？</h2><br>    <pre><code class="hljs python copyable" lang="python">a, b = b, a<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-92">83 map函数和reduce函数？</h2><br>    <pre><code class="hljs python copyable" lang="python">map(<span            class="hljs-keyword">lambda</span> x: x * x, [<span class="hljs-number">1</span>, <span            class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span            class="hljs-number">4</span>])   <span            class="hljs-comment"># 使用 lambda</span><br><span class="hljs-comment"># [1, 4, 9, 16]</span><br>reduce(<span class="hljs-keyword">lambda</span> x, y: x * y, [<span class="hljs-number">1</span>, <span                class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>])  <span                class="hljs-comment"># 相当于 ((1 * 2) * 3) * 4</span><br><span class="hljs-comment"># 24</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-93">84 回调函数，如何通信的?</h2><br>    <p>回调函数是把函数的指针(地址)作为参数传递给另一个函数，将整个函数当作一个对象，赋值给调用的函数。</p><br>    <h2 class="heading" data-id="heading-94">85 Python主要的内置数据类型都有哪些？ print dir( ‘a ’) 的输出？</h2><br>    <p>内建类型：布尔类型，数字，字符串，列表，元组，字典，集合</p><br>    <p>输出字符串’a’的内建方法</p><br>    <h2 class="heading" data-id="heading-95">86 map(lambda x:xx，[y for y in range(3)])的输出？</h2><br>    <pre><code class="hljs python copyable" lang="python">[<span class="hljs-number">0</span>, <span            class="hljs-number">1</span>, <span class="hljs-number">4</span>]<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-96">87 hasattr() getattr() setattr() 函数使用详解？</h2><br>    <p>hasattr(object,name)函数:</p><br>    <p>判断一个对象里面是否有name属性或者name方法，返回bool值，有name属性（方法）返回True，否则返回False。</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">function_demo</span><span            class="hljs-params">(object)</span>:</span><br>    name = <span class="hljs-string">'demo'</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run</span><span            class="hljs-params">(self)</span>:</span><br>        <span class="hljs-keyword">return</span> <span class="hljs-string">"hello function"</span><br>functiondemo = function_demo()<br>res = hasattr(functiondemo, <span class="hljs-string">"name"</span>) <span                class="hljs-comment"># 判断对象是否有name属性，True</span><br>res = hasattr(functiondemo, <span class="hljs-string">"run"</span>) <span                class="hljs-comment"># 判断对象是否有run方法，True</span><br>res = hasattr(functiondemo, <span class="hljs-string">"age"</span>) <span                class="hljs-comment"># 判断对象是否有age属性，False</span><br>print(res)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>getattr(object, name[,default])函数：</p><br>    <p>获取对象object的属性或者方法，如果存在则打印出来，如果不存在，打印默认值，默认值可选。注意：如果返回的是对象的方法，则打印结果是：方法的内存地址，如果需要运行这个方法，可以在后面添加括号().</p><br>    <pre><code class="hljs python copyable" lang="python">functiondemo = function_demo()<br>getattr(functiondemo, <span class="hljs-string">"name"</span>)<span                class="hljs-comment"># 获取name属性，存在就打印出来 --- demo</span><br>getattr(functiondemo, <span class="hljs-string">"run"</span>) <span class="hljs-comment"># 获取run 方法，存在打印出方法的内存地址</span><br>getattr(functiondemo, <span class="hljs-string">"age"</span>) <span class="hljs-comment"># 获取不存在的属性，报错</span><br>getattr(functiondemo, <span class="hljs-string">"age"</span>, <span class="hljs-number">18</span>)<span                class="hljs-comment"># 获取不存在的属性，返回一个默认值</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>setattr(object, name, values)函数：</p><br>    <p>给对象的属性赋值，若属性不存在，先创建再赋值</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">function_demo</span><span            class="hljs-params">(object)</span>:</span><br>    name = <span class="hljs-string">"demo"</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run</span><span            class="hljs-params">(self)</span>:</span><br>        <span class="hljs-keyword">return</span> <span class="hljs-string">"hello function"</span><br>functiondemo = function_demo()<br>res = hasattr(functiondemo, <span class="hljs-string">"age"</span>) <span                class="hljs-comment"># 判断age属性是否存在，False</span><br>print(res)<br>setattr(functiondemo, <span class="hljs-string">"age"</span>, <span class="hljs-number">18</span>) <span                class="hljs-comment"># 对age属性进行赋值，无返回值</span><br>res1 = hasattr(functiondemo, <span class="hljs-string">"age"</span>) <span class="hljs-comment"># 再次判断属性是否存在，True</span><br><span class="copy-code-btn">复制代码</span></code></pre><br>    <p>综合使用</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-class"><span            class="hljs-keyword">class</span> <span class="hljs-title">function_demo</span><span            class="hljs-params">(object)</span>:</span><br>    name = <span class="hljs-string">"demo"</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run</span><span            class="hljs-params">(self)</span>:</span><br>        <span class="hljs-keyword">return</span> <span class="hljs-string">"hello function"</span><br>functiondemo = function_demo()<br>res = hasattr(functiondemo, <span class="hljs-string">"addr"</span>) <span class="hljs-comment"># 先判断是否存在</span><br><span class="hljs-keyword">if</span> res:<br>    addr = getattr(functiondemo, <span class="hljs-string">"addr"</span>)<br>    print(addr)<br><span class="hljs-keyword">else</span>:<br>    addr = getattr(functiondemo, <span class="hljs-string">"addr"</span>, setattr(functiondemo, <span                class="hljs-string">"addr"</span>, <span class="hljs-string">"北京首都"</span>))<br>    print(addr)<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-97">88 一句话解决阶乘函数？</h2><br>    <pre><code class="hljs python copyable" lang="python">reduce(<span class="hljs-keyword">lambda</span> x,y : x<em>y,range(<span            class="hljs-number">1</span>,n+<span class="hljs-number">1</span>))<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-98">89 对设计模式的理解，简述你了解的设计模式？</h2><br>    <p>设计模式是经过总结，优化的，对我们经常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样能够直接作用于我们的代码，反之，设计模式更为高级，它是一种必须在特定情形下实现的一种方法模板。<br>        常见的是工厂模式和单例模式</p><br>    <h2 class="heading" data-id="heading-99">90 请手写一个单例</h2><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-comment">#python2</span><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span><span        class="hljs-params">(object)</span>:</span><br>    __instance = <span class="hljs-keyword">None</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title"><strong>new</strong></span><span            class="hljs-params">(cls,*args,**kwargs)</span>:</span><br>        <span class="hljs-keyword">if</span> cls.__instance <span class="hljs-keyword">is</span> <span                class="hljs-keyword">None</span>:<br>            cls.__instance = objecet.<strong>new</strong>(cls)<br>            <span class="hljs-keyword">return</span> cls.__instance<br>        <span class="hljs-keyword">else</span>:<br>            <span class="hljs-keyword">return</span> cls.__instance<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-100">91 单例模式的应用场景有那些？</h2><br>    <p>单例模式应用的场景一般发现在以下条件下：<br>        资源共享的情况下，避免由于资源操作时导致的性能或损耗等，如日志文件，应用配置。<br>        控制资源的情况下，方便资源之间的互相通信。如线程池等，1,网站的计数器 2,应用配置 3.多线程池 4数据库配置 数据库连接池 5.应用程序的日志应用…</p><br>    <h2 class="heading" data-id="heading-101">92 用一行代码生成[1,4,9,16,25,36,49,64,81,100]</h2><br>    <pre><code class="hljs python copyable" lang="python">print([x</em>x <span class="hljs-keyword">for</span> x <span            class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, <span            class="hljs-number">11</span>)])<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-102">93 对装饰器的理解，并写出一个计时器记录方法执行性能的装饰器？</h2><br>    <p>装饰器本质上是一个callable object ，它可以让其他函数在不需要做任何代码变动的前提下增加额外功能，装饰器的返回值也是一个函数对象。</p><br>    <pre><code class="hljs python copyable" lang="python"><span class="hljs-keyword">import</span> time<br><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">timeit</span><span        class="hljs-params">(func)</span>:</span><br><span class="hljs-meta">    @wraps(func)</span><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span><span            class="hljs-params">(*args, **kwargs)</span>:</span><br>        start = time.clock()<br>        ret = func(*args, **kwargs)<br>        end = time.clock()<br>        print(<span class="hljs-string">‘used:’</span>,end-start)<br>        <span class="hljs-keyword">return</span> ret</p><pre><code>&lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; wrapper</code></pre><p><span class="hljs-meta">@timeit</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">foo</span><span        class="hljs-params">()</span>:</span><br>    print(<span class="hljs-string">‘in foo()’</span>foo())<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-103">94 解释以下什么是闭包？</h2><br>    <p>在函数内部再定义一个函数，并且这个函数用到了外边函数的变量，那么将这个函数以及用到的一些变量称之为闭包。</p><br>    <h2 class="heading" data-id="heading-104">95 函数装饰器有什么作用？</h2><br>    <p>装饰器本质上是一个callable<br>        object，它可以在让其他函数在不需要做任何代码的变动的前提下增加额外的功能。装饰器的返回值也是一个函数的对象，它经常用于有切面需求的场景。比如：插入日志，性能测试，事务处理，缓存。权限的校验等场景，有了装饰器就可以抽离出大量的与函数功能本身无关的雷同代码并发并继续使用。<br>        详细参考：<a target="_blank" href="https://manjusaka.itscoder.com/2018/02/23/something-about-decorator/"                rel="nofollow noopener noreferrer">manjusaka.itscoder.com/2018/02/23/…</a></p><br>    <h2 class="heading" data-id="heading-105">96 生成器，迭代器的区别？</h2><br>    <p>迭代器是遵循迭代协议的对象。用户可以使用 iter() 以从任何序列得到迭代器（如 list, tuple, dictionary, set 等）。另一个方法则是创建一个另一种形式的迭代器 —— generator<br>        。要获取下一个元素，则使用成员函数 next()（Python 2）或函数 next() function （Python 3） 。当没有元素时，则引发 StopIteration<br>        此例外。若要实现自己的迭代器，则只要实现 next()（Python 2）或 <code><strong>next</strong></code>()（ Python 3）</p><br>    <p>生成器（Generator），只是在需要返回数据的时候使用yield语句。每次next()被调用时，生成器会返回它脱离的位置（它记忆语句最后一次执行的位置和所有的数据值）</p><br>    <p>区别：<br>        生成器能做到迭代器能做的所有事，而且因为自动创建iter()和next()方法，生成器显得特别简洁，而且生成器也是高效的，使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法，当发生器终结时，还会自动抛出StopIteration异常。</p><br>    <h2 class="heading" data-id="heading-106">97 X是什么类型?</h2><br>    <p>X= (i for i in range(10))<br>        X是 generator类型</p><br>    <h2 class="heading" data-id="heading-107">98 请用一行代码 实现将1-N 的整数列表以3为单位分组</h2><br>    <pre><code class="hljs python copyable" lang="python">N =<span class="hljs-number">100</span><br><span class="hljs-keyword">print</span> ([[x <span class="hljs-keyword">for</span> x <span                class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>,<span                class="hljs-number">100</span>)] [i:i+<span                class="hljs-number">3</span>] <span class="hljs-keyword">for</span> i <span                class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>,<span                class="hljs-number">100</span>,<span                class="hljs-number">3</span>)])<br><span class="copy-code-btn">复制代码</span></code></pre><br>    <h2 class="heading" data-id="heading-108">99 Python中yield的用法?</h2><br>    <p><br>        yield就是保存当前程序执行状态。你用for循环的时候，每次取一个元素的时候就会计算一次。用yield的函数叫generator,和iterator一样，它的好处是不用一次计算所有元素，而是用一次算一次，可以节省很多空间，generator每次计算需要上一次计算结果，所以用yield,否则一return，上次计算结果就没了</p></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python常见的170道面试题全解析答案</title>
      <link href="cp/python/python-interview4/"/>
      <url>cp/python/python-interview4/</url>
      
        <content type="html"><![CDATA[<h2 id="语言特性"><a href="#语言特性" class="headerlink" title="语言特性"></a>语言特性</h2><h3 id="1-谈谈对-Python-和其他语言的区别"><a href="#1-谈谈对-Python-和其他语言的区别" class="headerlink" title="1. 谈谈对 Python 和其他语言的区别"></a>1. 谈谈对 Python 和其他语言的区别</h3><p>答：Python 是一门语法简洁优美,功能强大无比,应用领域非常广泛,具有强大完备的第三方库，他是一门强类型的可移植、可扩展，可嵌入的解释型编程语言，属于动态语言。  </p><p>拿 C 语言和 Python 比： Python 的第三方类库比较齐全并且使用简洁,很少代码就能实现一些功能，如果用 C 去实现相同的功能可能就比较复杂。但是对于速度来说 Python 的运行速度相较于 C 就比较慢了。所以有利的同时也有弊端，毕竟我们的学习成本降低了。  </p><h3 id="2-简述解释型和编译型编程语言"><a href="#2-简述解释型和编译型编程语言" class="headerlink" title="2. 简述解释型和编译型编程语言"></a>2. 简述解释型和编译型编程语言</h3><p>答：解释型语言是在运行程序的时候才翻译，每执行一次，要翻译一次，效率较低。 编译型就是直接编译成机型可以执行的，只翻译一次，所以效率相对来说较高。  </p><h3 id="3-Python-的解释器种类以及相关特点？"><a href="#3-Python-的解释器种类以及相关特点？" class="headerlink" title="3. Python 的解释器种类以及相关特点？"></a>3. Python 的解释器种类以及相关特点？</h3><p>答：  </p><p>CPython c 语言开发的，使用最广的解释器<br>IPython 基于 cPython 之上的一个交互式计时器，交互方式增强功能和 cPython 一样<br>PyPy 目标是执行效率，采用 JIT 技术。对 Python 代码进行动态编译，提高执行效率<br>JPython 运行在 Java 上的解释器，直接把 Python 代码编译成 Java 字节码执行<br>IronPython 运行在微软 .NET 平台上的解释器，把 Python 编译成 . NET 的字节码。  </p><h3 id="4-Python3-和-Python2-的区别？"><a href="#4-Python3-和-Python2-的区别？" class="headerlink" title="4. Python3 和 Python2 的区别？"></a>4. Python3 和 Python2 的区别？</h3><p>答： 这里例举 5 条  </p><p>print 在 Python3 中是函数必须加括号，Python2 中 print 为 class。<br>Python2 中使用 xrange，Python3 使用 range。<br>Python2 中默认的字符串类型默认是 ASCII，Python3 中默认的字符串类型是 Unicode。<br>Python2 中/的结果是整型，Python3 中是浮点类型。<br>Python2 中声明元类：<em>metaclass</em> = MetaClass,Python3 中声明元类：class newclass(metaclass=MetaClass)：pass。  </p><h3 id="5-Python3-和-Python2-中-int-和-long-区别？"><a href="#5-Python3-和-Python2-中-int-和-long-区别？" class="headerlink" title="5. Python3 和 Python2 中 int 和 long 区别？"></a>5. Python3 和 Python2 中 int 和 long 区别？</h3><p>答：Python2 有 int 和 long 类型。int 类型最大值不能超过 sys.maxint，而且这个最大值是平台相关的。可以通过在数字的末尾附上一个Ｌ来定义长整型，显然，它比 int 类型表示的数字范围更大。在 Python3 里，只有一种整数类型 int，大多数情况下，和 Python２中的长整型类似。  </p><h3 id="6-xrange-和-range-的区别？"><a href="#6-xrange-和-range-的区别？" class="headerlink" title="6. xrange 和 range 的区别？"></a>6. xrange 和 range 的区别？</h3><p>答：xrange 是在 Python2 中的用法，Python3 中只有 range xrange 用法与 range 完全相同，所不同的是生成的不是一个 list 对象，而是一个生成器。<br>编码规范  </p><h3 id="7-什么是-PEP8"><a href="#7-什么是-PEP8" class="headerlink" title="7. 什么是 PEP8?"></a>7. 什么是 PEP8?</h3><p>答：PEP8 通常会听别人提到，但是具体的指什么内容呢，简单介绍下。 《Python Enhancement Proposal #8》（8 号 Python 增强提案）又叫 PEP8，他针对的 Python 代码格式而编订的风格指南。  </p><h3 id="8-了解-Python-之禅么？"><a href="#8-了解-Python-之禅么？" class="headerlink" title="8. 了解 Python 之禅么？"></a>8. 了解 Python 之禅么？</h3><p>答：通过 import this 语句可以获取其具体的内容。它告诉大家如何写出高效整洁的代码。  </p><h3 id="9-了解-DocStrings-么？"><a href="#9-了解-DocStrings-么？" class="headerlink" title="9. 了解 DocStrings 么？"></a>9. 了解 DocStrings 么？</h3><p>答：DocStrings 文档字符串是一个重要工具，用于解释文档程序，帮助你的程序文档更加简单易懂。主要是解释代码作用的。  </p><h3 id="10-了解类型注解么？"><a href="#10-了解类型注解么？" class="headerlink" title="10. 了解类型注解么？"></a>10. 了解类型注解么？</h3><p>答：PEP 484 引入了类型提示，这使得可以对 Python 代码进行静态类型检查。 在使用 Ide 的时候可以获取到参数的类型，更方便传入参数。使用格式如下  </p><p>def foo(num： int) -&gt; None：<br>print(f”接收到的数字是：{num}”)  </p><p>介绍下这个简单例子，我们可以在函数的参数部分使用参数名+：+类型，来指定参数可以接受的类型，这里的话就是 num 参数为 int 类型，然后后面-&gt;接的是返回值的类型。这里返回值为 None，然后通过 fstring 格式化字符串输出传入的数字。  </p><h3 id="11-例举你知道-Python-对象的命名规范，例如方法或者类等"><a href="#11-例举你知道-Python-对象的命名规范，例如方法或者类等" class="headerlink" title="11. 例举你知道 Python 对象的命名规范，例如方法或者类等"></a>11. 例举你知道 Python 对象的命名规范，例如方法或者类等</h3><p>答：  </p><p>类：总是使用首字母大写单词串，如 MyClass。内部类可以使用额外的前导下划线。 变量：小写，由下划线连接各个单词。方法名类似 常量：常量名所有字母大写 等  </p><h3 id="12-Python-中的注释有几种？"><a href="#12-Python-中的注释有几种？" class="headerlink" title="12. Python 中的注释有几种？"></a>12. Python 中的注释有几种？</h3><p>答：总体来说分为两种，单行注释和多行注释。  </p><p>单行注释在行首是 #。<br>多行注释可以使用三个单引号或三个双引号，包括要注释的内容。  </p><h3 id="13-如何优雅的给一个函数加注释？"><a href="#13-如何优雅的给一个函数加注释？" class="headerlink" title="13. 如何优雅的给一个函数加注释？"></a>13. 如何优雅的给一个函数加注释？</h3><p>答：可以使用 docstring 配合类型注解  </p><h3 id="14-如何给变量加注释？"><a href="#14-如何给变量加注释？" class="headerlink" title="14. 如何给变量加注释？"></a>14. 如何给变量加注释？</h3><p>答：可以通过变量名：类型的方式如下  </p><p>a： str = “this is string type”  </p><h3 id="15-Python-代码缩进中是否支持-Tab-键和空格混用。"><a href="#15-Python-代码缩进中是否支持-Tab-键和空格混用。" class="headerlink" title="15. Python 代码缩进中是否支持 Tab 键和空格混用。"></a>15. Python 代码缩进中是否支持 Tab 键和空格混用。</h3><p>答：不允许 tab 键和空格键混用，这种现象在使用 sublime 的时候尤为明显。  </p><p>一般推荐使用 4 个空格替代 tab 键。  </p><h3 id="16-是否可以在一句-import-中导入多个库"><a href="#16-是否可以在一句-import-中导入多个库" class="headerlink" title="16. 是否可以在一句 import 中导入多个库?"></a>16. 是否可以在一句 import 中导入多个库?</h3><p>答：可以是可以，但是不推荐。因为一次导入多个模块可读性不是很好，所以一行导入一个模块会比较好。同样的尽量少用 from modulename import *，因为判断某个函数或者属性的来源有些困难，不方便调试，可读性也降低了。  </p><h3 id="17-在给-Py-文件命名的时候需要注意什么"><a href="#17-在给-Py-文件命名的时候需要注意什么" class="headerlink" title="17. 在给 Py 文件命名的时候需要注意什么?"></a>17. 在给 Py 文件命名的时候需要注意什么?</h3><p>答：给文件命名的时候不要和标准库库的一些模块重复，比如 abc。 另外要名字要有意义，不建议数字开头或者中文命名。  </p><h3 id="18-例举几个规范-Python-代码风格的工具"><a href="#18-例举几个规范-Python-代码风格的工具" class="headerlink" title="18. 例举几个规范 Python 代码风格的工具"></a>18. 例举几个规范 Python 代码风格的工具</h3><p>答：pylint 和 flake8<br>数据类型-字符串  </p><h3 id="19-列举-Python-中的基本数据类型？"><a href="#19-列举-Python-中的基本数据类型？" class="headerlink" title="19. 列举 Python 中的基本数据类型？"></a>19. 列举 Python 中的基本数据类型？</h3><p>答： Python3 中有六个标准的数据类型：字符串（String）、数字（Digit）、列表（List）、元组（Tuple）、集合（Sets）、字典（Dictionary）。  </p><h3 id="20-如何区别可变数据类型和不可变数据类型"><a href="#20-如何区别可变数据类型和不可变数据类型" class="headerlink" title="20. 如何区别可变数据类型和不可变数据类型"></a>20. 如何区别可变数据类型和不可变数据类型</h3><p>答： 从对象内存地址方向来说  </p><p>可变数据类型：在内存地址不变的情况下，值可改变（列表和字典是可变类型，但是字典中的 key 值必须是不可变类型）<br>不可变数据类型：内存改变，值也跟着改变。（数字，字符串，布尔类型，都是不可变类型）可以通过 id() 方法进行内存地址的检测。  </p><h3 id="21-将”hello-world”转换为首字母大写”Hello-World”"><a href="#21-将”hello-world”转换为首字母大写”Hello-World”" class="headerlink" title="21. 将”hello world”转换为首字母大写”Hello World”"></a>21. 将”hello world”转换为首字母大写”Hello World”</h3><p>答： 这个得看清题目是要求两个单词首字母都要大写，如果只是第一个单词首字母大小的话，只使用 capitalize 即可，但是这里是两个单词，所以用下面的方法。  </p><p>arr = “hello world”.split(“ “)<br>new_str = f”{arr[0].capitalize()} {arr[1].capitalize()}”<br>print(new_str)  </p><p>后来评论中有朋友提到了下面的方法，这里感谢这位朋友提醒。方案如下  </p><p>“hello world”.title()  </p><p>非常简单一句话搞定。  </p><h3 id="22-如何检测字符串中只含有数字"><a href="#22-如何检测字符串中只含有数字" class="headerlink" title="22. 如何检测字符串中只含有数字?"></a>22. 如何检测字符串中只含有数字?</h3><p>答：可以通过 isdigit 方法，例子如下  </p><p>s1 = “12223”.isdigit()<br>print(s1)  </p><p>s2 = “12223a”.isdigit()<br>print(s2)  </p><p>#结果如下：<br>#True<br>#False  </p><h3 id="23-将字符串”ilovechina”进行反转"><a href="#23-将字符串”ilovechina”进行反转" class="headerlink" title="23. 将字符串”ilovechina”进行反转"></a>23. 将字符串”ilovechina”进行反转</h3><p>答：  </p><p>s1 = “ilovechina”[：：-1]<br>print(s1)  </p><h3 id="24-Python-中的字符串格式化方式你知道哪些？"><a href="#24-Python-中的字符串格式化方式你知道哪些？" class="headerlink" title="24. Python 中的字符串格式化方式你知道哪些？"></a>24. Python 中的字符串格式化方式你知道哪些？</h3><p>答：%s，format，fstring(Python3.6 开始才支持，现在推荐的写法)  </p><h3 id="25-有一个字符串开头和末尾都有空格，比如“-adabdw-”，要求写一个函数把这个字符串的前后空格都去掉。"><a href="#25-有一个字符串开头和末尾都有空格，比如“-adabdw-”，要求写一个函数把这个字符串的前后空格都去掉。" class="headerlink" title="25. 有一个字符串开头和末尾都有空格，比如“ adabdw ”，要求写一个函数把这个字符串的前后空格都去掉。"></a>25. 有一个字符串开头和末尾都有空格，比如“ adabdw ”，要求写一个函数把这个字符串的前后空格都去掉。</h3><p>答：因为题目要是写一个函数所以我们不能直接使用 strip，不过我们可以把它封装到函数啊  </p><p>def strip_function(s1)：<br>return s1.strip()  </p><p>s1 = “ adabdw “<br>print(strip_function(s1))  </p><h3 id="26-获取字符串”123456“最后的两个字符。"><a href="#26-获取字符串”123456“最后的两个字符。" class="headerlink" title="26. 获取字符串”123456“最后的两个字符。"></a>26. 获取字符串”123456“最后的两个字符。</h3><p>答：切片使用的考察，最后两个即开始索引是 -2，代码如下  </p><p>a = “123456”<br>print(a[-2：：])  </p><h3 id="27-一个编码为-GBK-的字符串-S，要将其转成-UTF-8-编码的字符串，应如何操作？"><a href="#27-一个编码为-GBK-的字符串-S，要将其转成-UTF-8-编码的字符串，应如何操作？" class="headerlink" title="27. 一个编码为 GBK 的字符串 S，要将其转成 UTF-8 编码的字符串，应如何操作？"></a>27. 一个编码为 GBK 的字符串 S，要将其转成 UTF-8 编码的字符串，应如何操作？</h3><p>答：  </p><p>a= “S”.encode(“gbk”).decode(“utf-8”,’ignore’)<br>print(a)  </p><h3 id="28-（1）s-”info：xiaoZhang-33-shandong”，用正则切分字符串输出-‘info’-‘xiaoZhang’-‘33’-‘shandong’-。（2）a-“你好-中国-“，去除多余空格只留一个空格。"><a href="#28-（1）s-”info：xiaoZhang-33-shandong”，用正则切分字符串输出-‘info’-‘xiaoZhang’-‘33’-‘shandong’-。（2）a-“你好-中国-“，去除多余空格只留一个空格。" class="headerlink" title="28. （1）s=”info：xiaoZhang 33 shandong”，用正则切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]。（2）a = “你好 中国 “，去除多余空格只留一个空格。"></a>28. （1）s=”info：xiaoZhang 33 shandong”，用正则切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]。（2）a = “你好 中国 “，去除多余空格只留一个空格。</h3><p>答：  </p><p>（1）我们需要根据冒号或者空格切分  </p><p>import re  </p><p>s = “info：xiaoZhang 33 shandong”<br>res = re.split(r”：| “, s)<br>print(res)  </p><p>（2）  </p><p>s = “你好     中国  “<br>print(“ “.join(s.split()))  </p><h3 id="29-1-怎样将字符串转换为小写。-2-单引号、双引号、三引号的区别？"><a href="#29-1-怎样将字符串转换为小写。-2-单引号、双引号、三引号的区别？" class="headerlink" title="29. (1) 怎样将字符串转换为小写。 (2) 单引号、双引号、三引号的区别？"></a>29. (1) 怎样将字符串转换为小写。 (2) 单引号、双引号、三引号的区别？</h3><p>答： (1) 使用字符串的 lower() 方法。  </p><p>(2)单独使用单引号和双引号没什么区别，但是如果引号里面还需要使用引号的时候，就需要这两个配合使用了，然后说三引号，同样的三引号也分为三单引号和三双引号，两个都可以声名长的字符串时候使用，如果使用 docstring 就需要使用三双引号。<br>数据类型 - 列表  </p><h3 id="30-已知-AList-1-2-3-1-2-，对-AList-列表元素去重，写出具体过程。"><a href="#30-已知-AList-1-2-3-1-2-，对-AList-列表元素去重，写出具体过程。" class="headerlink" title="30. 已知 AList = [1,2,3,1,2]，对 AList 列表元素去重，写出具体过程。"></a>30. 已知 AList = [1,2,3,1,2]，对 AList 列表元素去重，写出具体过程。</h3><p>答：  </p><p>list(set(AList))  </p><h3 id="31-如何实现-“1-2-3”-变成-“1”-”2”-”3”"><a href="#31-如何实现-“1-2-3”-变成-“1”-”2”-”3”" class="headerlink" title="31. 如何实现 “1,2,3” 变成 [“1”,”2”,”3”]"></a>31. 如何实现 “1,2,3” 变成 [“1”,”2”,”3”]</h3><p>答：  </p><p>s = “1,2,3”<br>print(s.split(“,”))  </p><h3 id="32-给定两个-list，A-和-B，找出相同元素和不同元素"><a href="#32-给定两个-list，A-和-B，找出相同元素和不同元素" class="headerlink" title="32. 给定两个 list，A 和 B，找出相同元素和不同元素"></a>32. 给定两个 list，A 和 B，找出相同元素和不同元素</h3><p>答：  </p><p>A、B 中相同元素：print(set(A)&amp;set(B))<br>A、B 中不同元素：print(set(A)^set(B))  </p><h3 id="33-1-2-3-4-5-6-一行代码展开该列表，得出-1-2-3-4-5-6"><a href="#33-1-2-3-4-5-6-一行代码展开该列表，得出-1-2-3-4-5-6" class="headerlink" title="33. [[1,2],[3,4],[5,6]] 一行代码展开该列表，得出 [1,2,3,4,5,6]"></a>33. [[1,2],[3,4],[5,6]] 一行代码展开该列表，得出 [1,2,3,4,5,6]</h3><p>答：  </p><p>l = [[1,2],[3,4],[5,6]]<br>x=[j for i in l for j in i]<br>print(x)  </p><h3 id="34-合并列表-1-5-7-9-和-2-2-6-8"><a href="#34-合并列表-1-5-7-9-和-2-2-6-8" class="headerlink" title="34. 合并列表 [1,5,7,9] 和 [2,2,6,8]"></a>34. 合并列表 [1,5,7,9] 和 [2,2,6,8]</h3><p>答：使用 extend 和 + 都可以。  </p><p>a = [1,5,7,9]<br>b = [2,2,6,8]<br>a.extend(b)<br>print(a)  </p><h3 id="35-如何打乱一个列表的元素？"><a href="#35-如何打乱一个列表的元素？" class="headerlink" title="35. 如何打乱一个列表的元素？"></a>35. 如何打乱一个列表的元素？</h3><p>答：  </p><p>import random  </p><p>a = [1, 2, 3, 4, 5]<br>random.shuffle(a)<br>print(a)  </p><p>数据类型 - 字典  </p><h3 id="36-字典操作中-del-和-pop-有什么区别"><a href="#36-字典操作中-del-和-pop-有什么区别" class="headerlink" title="36. 字典操作中 del 和 pop 有什么区别"></a>36. 字典操作中 del 和 pop 有什么区别</h3><p>答：del 可以根据索引（元素所在位置）来删除的，没有返回值。 pop 可以根据索引弹出一个值，然后可以接收它的返回值。  </p><h3 id="37-按照字典的内的年龄排序"><a href="#37-按照字典的内的年龄排序" class="headerlink" title="37. 按照字典的内的年龄排序"></a>37. 按照字典的内的年龄排序</h3><p>d1 = [<br>{‘name’：’alice’, ‘age’：38},<br>{‘name’：’bob’, ‘age’：18},<br>{‘name’：’Carl’, ‘age’：28},<br>]  </p><p>答：  </p><p>d1 = [<br>{‘name’： ‘alice’, ‘age’： 38},<br>{‘name’： ‘bob’, ‘age’： 18},<br>{‘name’： ‘Carl’, ‘age’： 28},<br>]  </p><p>print(sorted(d1, key=lambda x：x[“age”]))  </p><h3 id="38-请合并下面两个字典-a-“A”：1-”B”：2-b-“C”：3-”D”：4"><a href="#38-请合并下面两个字典-a-“A”：1-”B”：2-b-“C”：3-”D”：4" class="headerlink" title="38. 请合并下面两个字典 a = {“A”：1,”B”：2},b = {“C”：3,”D”：4}"></a>38. 请合并下面两个字典 a = {“A”：1,”B”：2},b = {“C”：3,”D”：4}</h3><p>答： 合并字典方法很多，可以使用 a.update(b) 或者下面字典解包的方式  </p><p>a = {“A”：1,”B”：2}<br>b = {“C”：3,”D”：4}<br>print({**a,**b})  </p><h3 id="39-如何使用生成式的方式生成一个字典，写一段功能代码。"><a href="#39-如何使用生成式的方式生成一个字典，写一段功能代码。" class="headerlink" title="39. 如何使用生成式的方式生成一个字典，写一段功能代码。"></a>39. 如何使用生成式的方式生成一个字典，写一段功能代码。</h3><p>答：  </p><h1 id="需求-3：-把字典的-key-和-value-值调换；"><a href="#需求-3：-把字典的-key-和-value-值调换；" class="headerlink" title="需求 3： 把字典的 key 和 value 值调换；"></a>需求 3： 把字典的 key 和 value 值调换；</h1><p>d = {‘a’：’1’, ‘b’：’2’}  </p><p>print({v：k for k,v in d.items()})  </p><h3 id="40-如何把元组-“a”-”b”-和元组-1-2-，变为字典-“a”：1-”b”：2"><a href="#40-如何把元组-“a”-”b”-和元组-1-2-，变为字典-“a”：1-”b”：2" class="headerlink" title="40. 如何把元组 (“a”,”b”) 和元组 (1,2)，变为字典 {“a”：1,”b”：2}"></a>40. 如何把元组 (“a”,”b”) 和元组 (1,2)，变为字典 {“a”：1,”b”：2}</h3><p>答 zip 的使用，但是最后记得把 zip 对象再转换为字典。  </p><p>a = (“a”, “b”)<br>b = (1, 2)<br>print(dict(zip(a, b)))  </p><p>数据类型 - 综合  </p><h3 id="41-下列字典对象键类型不正确的是？"><a href="#41-下列字典对象键类型不正确的是？" class="headerlink" title="41. 下列字典对象键类型不正确的是？"></a>41. 下列字典对象键类型不正确的是？</h3><p>A：{1：0,2：0,3：0}<br>B：{“a”：0, “b”：0, “c”：0}<br>C： {(1,2)：0, (2,3)：0}<br>D： {[1,2]：0, [2,3]：0}  </p><p>答：D 因为只有可 hash 的对象才能做字典的键，列表是可变类型不是可 hash 对象，所以不能用列表做为字典的键。  </p><h3 id="42-如何交换字典-“A”：1-”B”：2-的键和值"><a href="#42-如何交换字典-“A”：1-”B”：2-的键和值" class="headerlink" title="42. 如何交换字典 {“A”：1,”B”：2}的键和值"></a>42. 如何交换字典 {“A”：1,”B”：2}的键和值</h3><p>答：  </p><p>s =  {“A”：1,”B”：2}  </p><p>#方法一：<br>dict_new = {value:key for key，value in s.items()}  </p><h1 id="方法二："><a href="#方法二：" class="headerlink" title="方法二："></a>方法二：</h1><p>new_s= dict(zip(s.values()，s.keys()))  </p><h3 id="43-Python-里面如何实现-tuple-和-list-的转换？"><a href="#43-Python-里面如何实现-tuple-和-list-的转换？" class="headerlink" title="43. Python 里面如何实现 tuple 和 list 的转换？"></a>43. Python 里面如何实现 tuple 和 list 的转换？</h3><p>答： Python 中的类型转换，一般通过类型强转即可完成 tuple 转 list 是 list() 方法 list 转 tuple 使用 tuple() 方法  </p><h3 id="44-我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？"><a href="#44-我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？" class="headerlink" title="44. 我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？"></a>44. 我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？</h3><p>答： 这个题目考察了 Python 标准库的 itertools 模快的掌握情况，该模块提供了操作生成器的一些方法。 对于生成器类型我们使用 islice 方法来实现切片的功能。例子如下  </p><p>from itertools import islice<br>gen = iter(range(10)) #iter()函数用来生成迭代器<br>#第一个参数是迭代器，第二个参数起始索引，第三个参数结束索引，不支持负数索引<br>for i in islice(gen,0,4)：<br>print(i)  </p><h3 id="45-请将-i-for-i-in-range-3-改成生成器"><a href="#45-请将-i-for-i-in-range-3-改成生成器" class="headerlink" title="45. 请将 [i for i in range(3)] 改成生成器"></a>45. 请将 [i for i in range(3)] 改成生成器</h3><p>答：通过把列表生产式的中括号，改为小括号我们就实现了生产器的功能即，  </p><p>(i for i in range(3))  </p><h3 id="46-a-”hello”-和-b-”你好”-编码成-bytes-类型"><a href="#46-a-”hello”-和-b-”你好”-编码成-bytes-类型" class="headerlink" title="46. a=”hello” 和 b=”你好” 编码成 bytes 类型"></a>46. a=”hello” 和 b=”你好” 编码成 bytes 类型</h3><p>答： 这个题目一共三种方式，第一种是在字符串的前面加一个 b，第二种可以使用 bytes 方法，第三种使用字符串 encode 方法。具体代码如下，abc 代表三种情况  </p><p>a = b”hello”<br>b = bytes(“你好”, “utf-8”)<br>c = “你好”.encode(“utf-8”)<br>print(a, b, c)  </p><h3 id="47-下面的代码输出结果是什么？"><a href="#47-下面的代码输出结果是什么？" class="headerlink" title="47. 下面的代码输出结果是什么？"></a>47. 下面的代码输出结果是什么？</h3><p>a = (1,2,3,[4,5,6,7],8)<br>a[2] = 2  </p><p>答： 我们知道元组里的元素是不能改变的所以这个题目的答案是出现异常。  </p><h3 id="48-下面的代码输出的结果是什么"><a href="#48-下面的代码输出的结果是什么" class="headerlink" title="48. 下面的代码输出的结果是什么?"></a>48. 下面的代码输出的结果是什么?</h3><p>a = (1,2,3,[4,5,6,7],8)<br>a[3][0] = 2  </p><p>答：前面我说了元组的里元素是不能改变的，这句话严格来说是不准确的，如果元组里面元素本身就是可变类型，比如列表，那么在操作这个元素里的对象时，其内存地址也是不变的。a[3] 对应的元素是列表，然后对列表第一个元素赋值，所以最后的结果是： (1,2,3,[2,5,6,7],8)<br>操作类题目  </p><h3 id="49-Python-交换两个变量的值"><a href="#49-Python-交换两个变量的值" class="headerlink" title="49. Python 交换两个变量的值"></a>49. Python 交换两个变量的值</h3><p>答：在 Python 中交换两个对象的值通过下面的方式即可  </p><p>a , b = b ,a   </p><p>但是需要强调的是这并不是元组解包，通过 dis 模块可以发现，这是交换操作的字节码是 ROT_TWO，意思是在栈的顶端做两个值的互换操作。  </p><h3 id="50-在读文件操作的时候会使用-read、readline-或者-readlines，简述它们各自的作用"><a href="#50-在读文件操作的时候会使用-read、readline-或者-readlines，简述它们各自的作用" class="headerlink" title="50. 在读文件操作的时候会使用 read、readline 或者 readlines，简述它们各自的作用"></a>50. 在读文件操作的时候会使用 read、readline 或者 readlines，简述它们各自的作用</h3><p>答：.read() 每次读取整个文件，它通常用于将文件内容放到一个字符串变量中。如果希望一行一行的输出那么就可以使用 readline()，该方法会把文件的内容加载到内存，所以对于对于大文件的读取操作来说非常的消耗内存资源，此时就可以通过 readlines 方法，将文件的句柄生成一个生产器，然后去读就可以了。  </p><h3 id="51-json-序列化时，可以处理的数据类型有哪些？如何定制支持-datetime-类型？"><a href="#51-json-序列化时，可以处理的数据类型有哪些？如何定制支持-datetime-类型？" class="headerlink" title="51. json 序列化时，可以处理的数据类型有哪些？如何定制支持 datetime 类型？"></a>51. json 序列化时，可以处理的数据类型有哪些？如何定制支持 datetime 类型？</h3><p>答： 可以处理的数据类型是 str、int、list、tuple、dict、bool、None, 因为 datetime 类不支持 json 序列化，所以我们对它进行拓展。  </p><h1 id="自定义时间序列化"><a href="#自定义时间序列化" class="headerlink" title="自定义时间序列化"></a>自定义时间序列化</h1><p>import json<br>from datetime import datetime, date  </p><h1 id="JSONEncoder-不知道怎么去把这个数据转换成-json-字符串的时候"><a href="#JSONEncoder-不知道怎么去把这个数据转换成-json-字符串的时候" class="headerlink" title="JSONEncoder 不知道怎么去把这个数据转换成 json 字符串的时候"></a>JSONEncoder 不知道怎么去把这个数据转换成 json 字符串的时候</h1><h1 id="，它就会去调-default-函数-所以都是重写这个函数来处理它本身不支持的数据类型，"><a href="#，它就会去调-default-函数-所以都是重写这个函数来处理它本身不支持的数据类型，" class="headerlink" title="，它就会去调 default()函数,所以都是重写这个函数来处理它本身不支持的数据类型，"></a>，它就会去调 default()函数,所以都是重写这个函数来处理它本身不支持的数据类型，</h1><h1 id="default-函数默-认是直接抛异常的。"><a href="#default-函数默-认是直接抛异常的。" class="headerlink" title="default()函数默#认是直接抛异常的。"></a>default()函数默#认是直接抛异常的。</h1><p>class DateToJson(json.JSONEncoder)：<br>def default(self, obj)：<br>    if isinstance(obj, datetime)：<br>        return obj.strftime(‘%Y-%m-%d %H：%M：%S’)<br>    elif isinstance(obj, date)：<br>        return obj.strftime(‘%Y-%m-%d’)<br>    else：<br>        return json.JSONEncoder.default(self, obj)  </p><p>d = {‘name’： ‘cxa’, ‘data’： datetime.now()}<br>print(json.dumps(d, cls=DateToJson))  </p><h3 id="52-json-序列化时，默认遇到中文会转换成-unicode，如果想要保留中文怎么办？"><a href="#52-json-序列化时，默认遇到中文会转换成-unicode，如果想要保留中文怎么办？" class="headerlink" title="52. json 序列化时，默认遇到中文会转换成 unicode，如果想要保留中文怎么办？"></a>52. json 序列化时，默认遇到中文会转换成 unicode，如果想要保留中文怎么办？</h3><p>答：可以通过 json.dumps 的 ensure_ascii 参数解决，代码示例如下：  </p><p>import json<br>a=json.dumps({“name”：”张三”},ensure_ascii=False)<br>print(a)  </p><h3 id="53-有两个磁盘文件-A-和-B，各存放一行字母，要求把这两个文件中的信息合并-按字母顺序排列-，输出到一个新文件-C-中。"><a href="#53-有两个磁盘文件-A-和-B，各存放一行字母，要求把这两个文件中的信息合并-按字母顺序排列-，输出到一个新文件-C-中。" class="headerlink" title="53. 有两个磁盘文件 A 和 B，各存放一行字母，要求把这两个文件中的信息合并(按字母顺序排列)，输出到一个新文件 C 中。"></a>53. 有两个磁盘文件 A 和 B，各存放一行字母，要求把这两个文件中的信息合并(按字母顺序排列)，输出到一个新文件 C 中。</h3><p>答：  </p><p>#文件 A.txt 内容为 ASDCF<br>#文件 B.txt 内容为 EFGGTG<br>with open(“A.txt”) as f1：<br>f1_txt = f1.readline()<br>with open(“B.txt”) as f2：<br>f2_txt = f2.readline()<br>f3_txt = f1_txt + f2_txt  </p><p>f3_list = sorted(f3_txt)  </p><p>with open(“C.txt”, “a+”) as f：<br> f.write(“”.join(f3_list))  </p><p>输出的文件 C 的内容为 ACDEFFGGGST  </p><h3 id="54-如果当前的日期为-20190530，要求写一个函数输出-N-天后的日期，-比如-N-为-2，则输出-20190601-。"><a href="#54-如果当前的日期为-20190530，要求写一个函数输出-N-天后的日期，-比如-N-为-2，则输出-20190601-。" class="headerlink" title="54. 如果当前的日期为 20190530，要求写一个函数输出 N 天后的日期，(比如 N 为 2，则输出 20190601)。"></a>54. 如果当前的日期为 20190530，要求写一个函数输出 N 天后的日期，(比如 N 为 2，则输出 20190601)。</h3><p>答：这个题目考察的是 datetime 里的 timedelta 方法的使用，参数可选、默认值都为 0：datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) 通过这个参数可以指定不同的日期类型进行加减操作，这里我们需要改的是 days，代码如下  </p><p>import datetime  </p><p>def datetime_operate(n： int)：<br>now = datetime.datetime.now()  # 获取当前时间<br>_new_date = now + datetime.timedelta(days=n)  # 获取指定天数后的新日期<br>new_date = _new_date.strftime(“%Y%m%d”)  # 转换为指定的输出格式<br>return new_date  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>print(datetime_operate(4))  </p><h3 id="55-写一个函数，接收整数参数-n，返回一个函数，函数的功能是把函数的参数和-n-相乘并把结果返回。"><a href="#55-写一个函数，接收整数参数-n，返回一个函数，函数的功能是把函数的参数和-n-相乘并把结果返回。" class="headerlink" title="55. 写一个函数，接收整数参数 n，返回一个函数，函数的功能是把函数的参数和 n 相乘并把结果返回。"></a>55. 写一个函数，接收整数参数 n，返回一个函数，函数的功能是把函数的参数和 n 相乘并把结果返回。</h3><p>答：这个题目考查了闭包的使用代码示例如下，返回函数之类型是函数对象。  </p><p>def mul_operate(num):<br>def g(val):<br>    return num * val  </p><p>return g  </p><p>m = mul_operate(8)<br>print(m(5))  </p><h3 id="56-下面代码会存在什么问题，如何改进？"><a href="#56-下面代码会存在什么问题，如何改进？" class="headerlink" title="56. 下面代码会存在什么问题，如何改进？"></a>56. 下面代码会存在什么问题，如何改进？</h3><p>def strappend(num)：<br>str=’first’<br>for i in range(num)：<br>    str+=str(i)<br>return str  </p><p>答： 首先不应该使用 Python 的内置类似 str 作为变量名这里我把它改为了 s,另外在Python,str 是个不可变对象，每次迭代都会生成新的存储空间，num 越大，创建的 str 对象就会越多，内存消耗越大。使用 yield 改成生成器即可, 还有一点就是命名规范的位置，函数名改为_分割比较好，完整的代码如下:  </p><p>def str_append(num):<br>s = ‘first’<br>for i in range(num):<br>    s += str(i)<br>    yield s  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘:<br>for i in str_append(3):<br>    print(i)  </p><h3 id="57-一行代码输出-1-100-之间的所有偶数。"><a href="#57-一行代码输出-1-100-之间的所有偶数。" class="headerlink" title="57. 一行代码输出 1-100 之间的所有偶数。"></a>57. 一行代码输出 1-100 之间的所有偶数。</h3><p>答：可以通过列表生成式，然后使用与操作如果如 1 与之后结果为 0 则表明为偶数，等于 1 则为奇数。  </p><h1 id="方法1"><a href="#方法1" class="headerlink" title="方法1"></a>方法1</h1><p>print([i for i in range(1, 101) if i &amp; 0x1 == 0])  </p><h1 id="方法2：测试发现方法二效率更高"><a href="#方法2：测试发现方法二效率更高" class="headerlink" title="方法2：测试发现方法二效率更高"></a>方法2：测试发现方法二效率更高</h1><p>print(list(range(2, 101, 2)))  </p><h3 id="58-with-语句的作用，写一段代码？"><a href="#58-with-语句的作用，写一段代码？" class="headerlink" title="58. with 语句的作用，写一段代码？"></a>58. with 语句的作用，写一段代码？</h3><p>with 语句适用于对资源进行访问的场合，确保不管使用过程中是否发生异常都会执行必要的“清理”操作，释放资源，比如文件使用后自动关闭、线程中锁的自动获取和释放等。  </p><p>其他的内容看下面我之前写的代码。  </p><p>#一般访问文件资源时我们会这样处理：  </p><p>f = open(<br>‘c：\test.txt’, ‘r’)<br>data = f.read()<br>f.close()  </p><h1 id="这样写没有错，但是容易犯两个毛病："><a href="#这样写没有错，但是容易犯两个毛病：" class="headerlink" title="这样写没有错，但是容易犯两个毛病："></a>这样写没有错，但是容易犯两个毛病：</h1><h1 id="1-如果在读写时出现异常而忘了异常处理。"><a href="#1-如果在读写时出现异常而忘了异常处理。" class="headerlink" title="1. 如果在读写时出现异常而忘了异常处理。"></a>1. 如果在读写时出现异常而忘了异常处理。</h1><h1 id="2-忘了关闭文件句柄"><a href="#2-忘了关闭文件句柄" class="headerlink" title="2. 忘了关闭文件句柄"></a>2. 忘了关闭文件句柄</h1><p>#以下的加强版本的写法：  </p><p>f = open(‘c：\test.txt’, ‘r’)<br>try：<br>data = f.read()<br>finally：<br>f.close()  </p><p>#以上的写法就可以避免因读取文件时异常的发生而没有关闭问题的处理了。代码长了一些。<br>#但使用 with 有更优雅的写法：  </p><p>with open(r’c：\test.txt’, ‘r’) as f：<br>data = f.read()<br>#with 的实现  </p><p>class Test：<br>def <strong>enter</strong>(self)：<br>    print(‘<strong>enter</strong>() is call!’)<br>    return self  </p><p>def dosomething(self)：<br>    print(‘dosomethong!’)  </p><p>def <strong>exit</strong>(self, exc_type, exc_value, traceback)：<br>    print(‘<strong>exit</strong>() is call!’)<br>    print(f’type：{exc_type}’)<br>    print(f’value：{exc_value}’)<br>    print(f’trace：{traceback}’)<br>    print(‘<strong>exit()</strong> is call!’)  </p><p>with Test() as sample：<br>  pass  </p><p>#当对象被实例化时，就会主动调用__enter__()方法，任务执行完成后就会调用__exit__()方法，<br>#另外，注意到，<strong>exit</strong>()方法是带有三个参数的(exc_type, exc_value, traceback),<br>#依据上面的官方说明：如果上下文运行时没有异常发生，那么三个参数都将置为 None,<br>#这里三个参数由于没有发生异常，的确是置为了 None, 与预期一致.  </p><h1 id="修改后不出异常了"><a href="#修改后不出异常了" class="headerlink" title="修改后不出异常了"></a>修改后不出异常了</h1><p>class Test：<br>def <strong>enter</strong>(self)：<br>    print(‘<strong>enter</strong>() is call!’)<br>    return self  </p><p>def dosomething(self)：<br>    x = 1/0<br>    print(‘dosomethong!’)  </p><p>def <strong>exit</strong>(self, exc_type, exc_value, traceback)：<br>    print(‘<strong>exit</strong>() is call!’)<br>    print(f’type：{exc_type}’)<br>    print(f’value：{exc_value}’)<br>    print(f’trace：{traceback}’)<br>    print(‘<strong>exit()</strong> is call!’)<br>    return True  </p><p>with Test() as sample：  </p><h3 id="59-Python-字典和-json-字符串相互转化方法"><a href="#59-Python-字典和-json-字符串相互转化方法" class="headerlink" title="59. Python 字典和 json 字符串相互转化方法"></a>59. Python 字典和 json 字符串相互转化方法</h3><p>答:  </p><p>在 Python 中使用 dumps 方法 将 dict 对象转为 Json 对象，使用 loads 方法可以将 Json 对象转为 dict 对象。  </p><p>dic = {‘a’: 123, ‘b’: “456”, ‘c’: “liming”}<br>json_str = json.dumps(dic)<br>dic2 = json.loads(json_str)<br>print(dic2)<br>打印：<br>‘{“a”: 123, “b”: “456”, “c”: “liming”}’<br>{‘a’: 123, ‘b’: ‘456’, ‘c’: ‘liming’}  </p><p>我们再来看一个特殊的例子  </p><p>import json<br>dic = {‘a’： 123, ‘b’： “456”, ‘c’： “liming”}<br>dic_str = json.loads(str(dic).replace(“‘“, “&quot;“))<br>print(dic_str)  </p><p>下面我解释下上面代码是测试什么:  </p><p>首先 json.loads(jsonstr) 这里面的参数只能是 jsonstr 格式的字符串.<br>当我们使用 str 将字典 dic 转化为字符串以后，得到的结果为:”{‘a’: 123, ‘b’: ‘456’, ‘c’: ‘liming’}”。<br>如果直接使用 json.loads(str(dic)) 你会发现出现错误，原因就是，单引号的字符串不符合Json的标准格式所以再次使用了 replace(“‘“, “&quot;“)。得到字典<br>其实这个例子主要目的是告诉大家 Json 的标准格式是不支持单引号型字符串的，否则会出现以下错误。<br>json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)  </p><h3 id="60-请写一个-Python-逻辑，计算一个文件中的大写字母数量"><a href="#60-请写一个-Python-逻辑，计算一个文件中的大写字母数量" class="headerlink" title="60. 请写一个 Python 逻辑，计算一个文件中的大写字母数量"></a>60. 请写一个 Python 逻辑，计算一个文件中的大写字母数量</h3><p>答：  </p><p>with open(‘A.txt’) as fs：<br>count = 0<br>for i in fs.read()：<br>    if i.isupper()：<br>        count += 1<br>print(count)  </p><h3 id="61-请写一段-Python连接Mongo数据库，然后的查询代码。"><a href="#61-请写一段-Python连接Mongo数据库，然后的查询代码。" class="headerlink" title="61. 请写一段 Python连接Mongo数据库，然后的查询代码。"></a>61. 请写一段 Python连接Mongo数据库，然后的查询代码。</h3><p>答:  </p><h1 id="coding-utf-8"><a href="#coding-utf-8" class="headerlink" title="-- coding: utf-8 --"></a>-<em>- coding: utf-8 -</em>-</h1><h1 id="Author-陈祥安"><a href="#Author-陈祥安" class="headerlink" title="@Author : 陈祥安"></a>@Author : 陈祥安</h1><p>import pymongo<br>db_configs = {<br>‘type’: ‘mongo’,<br>‘host’: ‘地址’,<br>‘port’: ‘端口’,<br>‘user’: ‘spider_data’,<br>‘passwd’: ‘密码’,<br>‘db_name’: ‘spider_data’<br>}  </p><p>class Mongo():<br>def <strong>init</strong>(self, db=db_configs[“db_name”], username=db_configs[“user”],<br>             password=db_configs[“passwd”]):<br>    self.client = pymongo.MongoClient(f’mongodb://{db_configs[“host”]}:db_configs[“port”]’)<br>    self.username = username<br>    self.password = password<br>    if self.username and self.password:<br>        self.db1 = self.client[db].authenticate(self.username, self.password)<br>    self.db1 = self.client[db]  </p><p>def find_data(self):<br>    # 获取状态为0的数据<br>    data = self.db1.test.find({“status”: 0})<br>    gen = (item for item in data)<br>    return gen  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘:<br>m = Mongo()<br>print(m.find_data())  </p><h3 id="62-说一说Redis的基本类型"><a href="#62-说一说Redis的基本类型" class="headerlink" title="62.说一说Redis的基本类型"></a>62.说一说Redis的基本类型</h3><p>答: Redis 支持五种数据类型： string（字符串） 、 hash（哈希）、list（列表） 、 set（集合） 及 zset(sorted set： 有序集合)。  </p><h3 id="63-请写一段-Python连接Redis数据库的代码。"><a href="#63-请写一段-Python连接Redis数据库的代码。" class="headerlink" title="63. 请写一段 Python连接Redis数据库的代码。"></a>63. 请写一段 Python连接Redis数据库的代码。</h3><p>答:  </p><p>from redis import StrictRedis, ConnectionPool<br>redis_url=”redis://:<a href="mailto:&#120;&#120;&#120;&#120;&#64;&#49;&#x31;&#x32;&#x2e;&#x32;&#55;&#46;&#49;&#48;&#x2e;&#49;&#x36;&#x38;">&#120;&#120;&#120;&#120;&#64;&#49;&#x31;&#x32;&#x2e;&#x32;&#55;&#46;&#49;&#48;&#x2e;&#49;&#x36;&#x38;</a>:6379/15”<br>pool = ConnectionPool.from_url(redis_url, decode_responses=True)<br>r= StrictRedis(connection_pool=pool)  </p><h3 id="64-请写一段-Python连接Mysql数据库的代码。"><a href="#64-请写一段-Python连接Mysql数据库的代码。" class="headerlink" title="64. 请写一段 Python连接Mysql数据库的代码。"></a>64. 请写一段 Python连接Mysql数据库的代码。</h3><p>答:  </p><p>conn = pymysql.connect(host=’localhost’,<br>port=3306, user=’root’,<br>passwd=’1234’, db=’user’, charset=’utf8mb4’)#声明mysql连接对象<br>cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)#查询结果以字典的形式<br>cursor.execute(sql语句字符串)#执行sql语句<br>conn.close()#关闭链接  </p><h3 id="65-了解Redis的事务么"><a href="#65-了解Redis的事务么" class="headerlink" title="65.了解Redis的事务么"></a>65.了解Redis的事务么</h3><p>答: 简单理解，可以认为 redis 事务是一些列 redis 命令的集合，并且有如下两个特点： 1.事务是一个单独的隔离操作：事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中，不会被其他客户端发送来的命令请求所打断。 2.事务是一个原子操作：事务中的命令要么全部被执行，要么全部都不执行。 一般来说，事务有四个性质称为ACID，分别是原子性，一致性，隔离性和持久性。 一个事务从开始到执行会经历以下三个阶段：  </p><p>开始事务<br>命令入队<br>执行事务 代码示例:  </p><p>import redis<br>import sys<br>def run():<br>try:<br>    conn=redis.StrictRedis(‘192.168.80.41’)  </p><h1 id="Python中redis事务是通过pipeline的封装实现的"><a href="#Python中redis事务是通过pipeline的封装实现的" class="headerlink" title="Python中redis事务是通过pipeline的封装实现的"></a>Python中redis事务是通过pipeline的封装实现的</h1><pre><code>pipe=conn.pipeline()  pipe.sadd(&#39;s001&#39;,&#39;a&#39;)  sys.exit()  #在事务还没有提交前退出，所以事务不会被执行。  pipe.sadd(&#39;s001&#39;,&#39;b&#39;)  pipe.execute()  pass  </code></pre><p>except Exception as err:<br>    print(err)<br>    pass<br>if <strong>name</strong>==”<strong>main</strong>“:<br>  run()  </p><h3 id="66-了解数据库的三范式么？"><a href="#66-了解数据库的三范式么？" class="headerlink" title="66.了解数据库的三范式么？"></a>66.了解数据库的三范式么？</h3><p>答: 经过研究和对使用中问题的总结，对于设计数据库提出了一些规范，这些规范被称为范式 一般需要遵守下面3范式即可: 第一范式（1NF）：强调的是列的原子性，即列不能够再分成其他几列。 第二范式（2NF）：首先是 1NF，另外包含两部分内容，一是表必须有一个主键；二是没有包含在主键中的列必须完全依赖于主键，而不能只依赖于主键的一部分。 第三范式（3NF）：首先是 2NF，另外非主键列必须直接依赖于主键，不能存在传递依赖。即不能存在：非主键列 A 依赖于非主键列 B，非主键列 B 依赖于主键的情况。  </p><h3 id="67-了解分布式锁么"><a href="#67-了解分布式锁么" class="headerlink" title="67.了解分布式锁么"></a>67.了解分布式锁么</h3><p>答: 分布式锁是控制分布式系统之间的同步访问共享资源的一种方式。 对于分布式锁的目标，我们必须首先明确三点：  </p><p>任何一个时间点必须只能够有一个客户端拥有锁。<br>不能够有死锁，也就是最终客户端都能够获得锁，尽管可能会经历失败。<br>错误容忍性要好，只要有大部分的Redis实例存活，客户端就应该能够获得锁。 分布式锁的条件 互斥性：分布式锁需要保证在不同节点的不同线程的互斥 可重入性：同一个节点上的同一个线程如果获取了锁之后，能够再次获取这个锁。 锁超时：支持超时释放锁，防止死锁 高效，高可用：加锁和解锁需要高效，同时也需要保证高可用防止分布式锁失效，可以增加降级。 支持阻塞和非阻塞：可以实现超时获取失败，tryLock(long timeOut) 支持公平锁和非公平锁  </p><p>分布式锁的实现方案 1、数据库实现（乐观锁） 2、基于zookeeper的实现 3、基于Redis的实现（推荐）  </p><h3 id="68-用-Python-实现一个-Reids-的分布式锁的功能"><a href="#68-用-Python-实现一个-Reids-的分布式锁的功能" class="headerlink" title="68.用 Python 实现一个 Reids 的分布式锁的功能"></a>68.用 Python 实现一个 Reids 的分布式锁的功能</h3><p>答:REDIS分布式锁实现的方式：SETNX + GETSET,NX是Not eXists的缩写，如SETNX命令就应该理解为：SET if Not eXists。 多个进程执行以下Redis命令：  </p><p>SETNX lock.foo &lt;current Unix time + lock timeout + 1&gt;  </p><p>如果 SETNX 返回1，说明该进程获得锁，SETNX将键 lock.foo 的值设置为锁的超时时间（当前时间 + 锁的有效时间）。 如果 SETNX 返回0，说明其他进程已经获得了锁，进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作，以获得锁。  </p><p>import time<br>import redis<br>from conf.config import REDIS_HOST, REDIS_PORT, REDIS_PASSWORD  </p><p>class RedisLock:<br>def <strong>init</strong>(self):<br>    self.conn = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, db=1)<br>    self._lock = 0<br>    self.lock_key = “”<br>@staticmethod<br>def my_float(timestamp):<br>    “””<br>    Args:<br>        timestamp:<br>    Returns:<br>        float或者0<br>        如果取出的是None，说明原本锁并没人用，getset已经写入，返回0，可以继续操作。<br>    “””<br>    if timestamp:<br>        return float(timestamp)<br>    else:<br>        #防止取出的值为None，转换float报错<br>        return 0  </p><p>@staticmethod<br>def get_lock(cls, key, timeout=10):<br>    cls.lock_key = f”{key}_dynamic_lock”<br>    while cls._lock != 1:<br>        timestamp = time.time() + timeout + 1<br>        cls._lock = cls.conn.setnx(cls.lock_key, timestamp)<br>        # if 条件中，可能在运行到or之后被释放，也可能在and之后被释放<br>        # 将导致 get到一个None，float失败。<br>        if cls._lock == 1 or (<br>                        time.time() &gt; cls.my_float(cls.conn.get(cls.lock_key)) and<br>                        time.time() &gt; cls.my_float(cls.conn.getset(cls.lock_key, timestamp))):<br>            break<br>        else:<br>            time.sleep(0.3)  </p><p>@staticmethod<br>def release(cls):<br>    if cls.conn.get(cls.lock_key) and time.time() &lt; cls.conn.get(cls.lock_key):<br>        cls.conn.delete(cls.lock_key)  </p><p>def redis_lock_deco(cls):<br>def _deco(func):<br>    def __deco(*args, **kwargs):<br>        cls.get_lock(cls, args[1])<br>        try:<br>            return func(*args, **kwargs)<br>        finally:<br>            cls.release(cls)<br>    return __deco<br>return _deco  </p><p>@redis_lock_deco(RedisLock())<br>def my_func():<br>print(“myfunc() called.”)<br>time.sleep(20)  </p><p>if <strong>name</strong> == “<strong>main</strong>“:<br>my_func()  </p><h3 id="69-写一段-Python-使用-mongo-数据库创建索引的代码"><a href="#69-写一段-Python-使用-mongo-数据库创建索引的代码" class="headerlink" title="69.写一段 Python 使用 mongo 数据库创建索引的代码:"></a>69.写一段 Python 使用 mongo 数据库创建索引的代码:</h3><p>答:  </p><h1 id="coding-utf-8-1"><a href="#coding-utf-8-1" class="headerlink" title="-- coding: utf-8 --"></a>-<em>- coding: utf-8 -</em>-</h1><h1 id="Time-2018-12-28-10-01-AM"><a href="#Time-2018-12-28-10-01-AM" class="headerlink" title="@Time : 2018/12/28 10:01 AM"></a>@Time : 2018/12/28 10:01 AM</h1><h1 id="Author-cxa"><a href="#Author-cxa" class="headerlink" title="@Author : cxa"></a>@Author : cxa</h1><p>import pymongo<br>db_configs = {<br>‘type’: ‘mongo’,<br>‘host’: ‘地址’,<br>‘port’: ‘端口’,<br>‘user’: ‘spider_data’,<br>‘passwd’: ‘密码’,<br>‘db_name’: ‘spider_data’<br>}  </p><p>class Mongo():<br>def <strong>init</strong>(self, db=db_configs[“db_name”], username=db_configs[“user”],<br>             password=db_configs[“passwd”]):<br>    self.client = pymongo.MongoClient(f’mongodb://{db_configs[“host”]}:{db_configs[“port”]}’)<br>    self.username = username<br>    self.password = password<br>    if self.username and self.password:<br>        self.db1 = self.client[db].authenticate(self.username, self.password)<br>    self.db1 = self.client[db]  </p><p>def add_index(self):<br>    “””<br>      通过create_index添加索引<br>    “””<br>    self.db1.test.create_index([(‘name’, pymongo.ASCENDING)], unique=True)  </p><p>def get_index(self,):<br>    “””<br>      查看索引列表<br>    “””<br>    indexlist=self.db1.test.list_indexes()<br>    for index in indexlist:<br>        print(index)  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘:<br>m = Mongo()<br>m.add_index()<br>print(m.get_index())  </p><p>高级特性  </p><h3 id="70-函数装饰器有什么作用？请列举说明？"><a href="#70-函数装饰器有什么作用？请列举说明？" class="headerlink" title="70. 函数装饰器有什么作用？请列举说明？"></a>70. 函数装饰器有什么作用？请列举说明？</h3><p>答： 装饰器就是一个函数，它可以在不需要做任何代码变动的前提下给一个函数增加额外功能，启动装饰的效果。 它经常用于有切面需求的场景，比如：插入日志、性能测试、事务处理、缓存、权限校验等场景。 下面是一个日志功能的装饰器  </p><p>from functools import wraps<br>def log(label)：<br>def decorate(func)：<br>   @wraps(func)<br>   def _wrap(*args,**kwargs)：<br>    try：<br>      func(*args,**kwargs)<br>      print(“name”,func.<strong>name</strong>)<br>    except Exception as e：<br>       print(e.args)<br>   return _wrap<br>return decorate      </p><p>@log(“info”)<br>def foo(a,b,c)：<br> print(a+b+c)<br> print(“in foo”)  </p><p>#decorate=decorate(foo)     </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>foo(1,2,3)<br> #decorate()  </p><h3 id="71-Python-垃圾回收机制？"><a href="#71-Python-垃圾回收机制？" class="headerlink" title="71. Python 垃圾回收机制？"></a>71. Python 垃圾回收机制？</h3><p>答：Python 不像 C++，Java 等语言一样，他们可以不用事先声明变量类型而直接对变量进行赋值。对 Python 语言来讲，对象的类型和内存都是在运行时确定的。这也是为什么我们称 Python 语言为动态类型的原因。  </p><p>主要体现在下面三个方法：  </p><h3 id="1-引用计数机制-2-标记-清除-3-分代回收"><a href="#1-引用计数机制-2-标记-清除-3-分代回收" class="headerlink" title="1.引用计数机制 2.标记-清除 3.分代回收"></a>1.引用计数机制 2.标记-清除 3.分代回收</h3><h3 id="72-魔法函数-call-怎么使用"><a href="#72-魔法函数-call-怎么使用" class="headerlink" title="72. 魔法函数 _call_怎么使用?"></a>72. 魔法函数 _call_怎么使用?</h3><p>答： <em>call</em> 可以把类实例当做函数调用。 使用示例如下  </p><p>class Bar：<br>def <strong>call</strong>(self, *args, **kwargs)：<br>    print(‘in call’)  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>b = Bar()<br>b()  </p><h3 id="73-如何判断一个对象是函数还是方法？"><a href="#73-如何判断一个对象是函数还是方法？" class="headerlink" title="73. 如何判断一个对象是函数还是方法？"></a>73. 如何判断一个对象是函数还是方法？</h3><p>答：看代码已经结果就懂了  </p><p>from types import MethodType, FunctionType  </p><p>class Bar：<br>def foo(self)：<br>    pass  </p><p>def foo2()：<br>pass  </p><p>def run()：<br>print(“foo 是函数”, isinstance(Bar().foo, FunctionType))<br>print(“foo 是方法”, isinstance(Bar().foo, MethodType))<br>print(“foo2 是函数”, isinstance(foo2, FunctionType))<br>print(“foo2 是方法”, isinstance(foo2, MethodType))  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>run()  </p><p>输出  </p><p>foo 是函数 False<br>foo 是方法 True<br>foo2 是函数 True<br>foo2 是方法 False  </p><h3 id="74-classmethod-和-staticmethod-用法和区别"><a href="#74-classmethod-和-staticmethod-用法和区别" class="headerlink" title="74. @classmethod 和 @staticmethod 用法和区别"></a>74. @classmethod 和 @staticmethod 用法和区别</h3><p>答： 相同之处：@staticmethod 和@classmethod 都可以直接类名.方法名()来调用，不用在示例化一个类。 @classmethod 我们要写一个只在类中运行而不在实例中运行的方法。如果我们想让方法不在实例中运行，可以这么做：  </p><p>def iget_no_of_instance(ins_obj)：<br>return ins_obj.<strong>class</strong>.no_inst  </p><p>class Kls(object)：<br>no_inst = 0  </p><p>def <strong>init</strong>(self)：<br>    Kls.no_inst = Kls.no_inst + 1  </p><p>ik1 = Kls()<br>ik2 = Kls()<br>print(iget_no_of_instance(ik1))  </p><p>@staticmethod 经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法  </p><p>IND = ‘ON’  </p><p>class Kls(object)：<br>def <strong>init</strong>(self, data)：<br>    self.data = data  </p><p>@staticmethod<br>def check_ind()：<br>    return (IND == ‘ON’)  </p><p>def do_reset(self)：<br>    if self.check_ind()：<br>        print(‘Reset done for：’, self.data)  </p><p>def set_db(self)：<br>    if self.check_ind()：<br>        self.db = ‘New db connection’<br>    print(‘DB connection made for： ‘, self.data)  </p><p>ik1 = Kls(12)<br>ik1.do_reset()<br>ik1.set_db()  </p><h3 id="75-Python-中的接口如何实现？"><a href="#75-Python-中的接口如何实现？" class="headerlink" title="75. Python 中的接口如何实现？"></a>75. Python 中的接口如何实现？</h3><p>答： 接口提取了一群类共同的函数，可以把接口当做一个函数的集合，然后让子类去实现接口中的函数。但是在 Python 中根本就没有一个叫做 interface 的关键字，如果非要去模仿接口的概念，可以使用抽象类来实现。抽象类是一个特殊的类，它的特殊之处在于只能被继承，不能被实例化。使用 abc 模块来实现抽象类。  </p><h3 id="76-Python-中的反射了解么"><a href="#76-Python-中的反射了解么" class="headerlink" title="76. Python 中的反射了解么?"></a>76. Python 中的反射了解么?</h3><p>答：Python 的反射机制设定较为简单，一共有四个关键函数分别是 getattr、hasattr、setattr、delattr。  </p><h3 id="77-metaclass-作用？以及应用场景？"><a href="#77-metaclass-作用？以及应用场景？" class="headerlink" title="77. metaclass 作用？以及应用场景？"></a>77. metaclass 作用？以及应用场景？</h3><p>答： metaclass 即元类，metaclass 是类似创建类的模板，所有的类都是通过他来 create 的(调用new)，这使得你可以自由的控制创建类的那个过程，实现你所需要的功能。 我们可以使用元类创建单例模式和实现 ORM 模式。  </p><h3 id="78-hasattr-、getattr-、setattr-的用法"><a href="#78-hasattr-、getattr-、setattr-的用法" class="headerlink" title="78. hasattr()、getattr()、setattr() 的用法"></a>78. hasattr()、getattr()、setattr() 的用法</h3><p>答：这三个方法属于 Python 的反射机制里面的，hasattr 可以判断一个对象是否含有某个属性，getattr 可以充当 get 获取对象属性的作用。而 setattr 可以充当 person.name = “liming”的赋值操作。代码示例如下：  </p><p>class Person()：<br>def <strong>init</strong>(self)：<br>    self.name = “liming”<br>    self.age = 12  </p><p>def show(self)：<br>    print(self.name)<br>    print(self.age)  </p><p>def set_name(self)：<br>    setattr(Person, “sex”, “男”)  </p><p>def get_name(self)：<br>    print(getattr(self, “name”))<br>    print(getattr(self, “age”))<br>    print(getattr(self, “sex”))  </p><p>def run()：<br>if hasattr(Person, “show”)：<br>    print(“判断 Person 类是否含有 show 方法”)  </p><p>Person().set_name()<br>Person().get_name()  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>run()  </p><h3 id="79-请列举你知道的-Python-的魔法方法及用途。"><a href="#79-请列举你知道的-Python-的魔法方法及用途。" class="headerlink" title="79. 请列举你知道的 Python 的魔法方法及用途。"></a>79. 请列举你知道的 Python 的魔法方法及用途。</h3><p>答：  </p><p>1 __init__：<br>类的初始化方法。它获取任何传给构造器的参数（比如我们调用 x = SomeClass(10, ‘foo’) ， __init__就会接到参数 10 和 ‘foo’ 。 __init__在 Python 的类定义中用的最多。  </p><p>2 __new__：<br>__new__是对象实例化时第一个调用的方法，它只取下 cls 参数，并把其他参数传给 <strong>init</strong> 。 __new__很少使用，但是也有它适合的场景，尤其是当类继承自一个像元组或者字符串这样不经常改变的类型的时候.  </p><p>3 __del__：<br>__new__和 __init__是对象的构造器， __del__是对象的销毁器。它并非实现了语句 del x (因此该语句不等同于 x.<strong>del</strong>())。而是定义了当对象被垃圾回收时的行为。 当对象需要在销毁时做一些处理的时候这个方法很有用，比如 socket 对象、文件对象。但是需要注意的是，当 Python 解释器退出但对象仍然存活的时候，__del__并不会 执行。 所以养成一个手工清理的好习惯是很重要的，比如及时关闭连接。  </p><h3 id="80-如何知道一个-Python-对象的类型？"><a href="#80-如何知道一个-Python-对象的类型？" class="headerlink" title="80. 如何知道一个 Python 对象的类型？"></a>80. 如何知道一个 Python 对象的类型？</h3><p>答：可以通过 type 方法  </p><h3 id="81-Python-的传参是传值还是传址？"><a href="#81-Python-的传参是传值还是传址？" class="headerlink" title="81. Python 的传参是传值还是传址？"></a>81. Python 的传参是传值还是传址？</h3><p>答：Python 中的传参即不是传值也不是传地址，传的是对象的引用。  </p><h3 id="82-Python-中的元类-metaclass-使用举例"><a href="#82-Python-中的元类-metaclass-使用举例" class="headerlink" title="82. Python 中的元类 (metaclass) 使用举例"></a>82. Python 中的元类 (metaclass) 使用举例</h3><p>答：可以使用元类实现一个单例模式，代码如下  </p><p>class Singleton(type)：<br>def <strong>init</strong>(self, *args, **kwargs)：<br>    print(“in <strong>init</strong>“)<br>    self.__instance = None<br>    super(Singleton, self).<strong>init</strong>(*args, **kwargs)  </p><p>def <strong>call</strong>(self, *args, **kwargs)：<br>    print(“in <strong>call</strong>“)<br>    if self.__instance is None：<br>        self.__instance = super(Singleton, self).<strong>call</strong>(*args, **kwargs)<br>    return self.__instance  </p><p>class Foo(metaclass=Singleton)：<br>pass  # 在代码执行到这里的时候，元类中的__new__方法和__init__方法其实已经被执行了，而不是在 Foo 实例化的时候执行。且仅会执行一次。  </p><p>foo1 = Foo()<br>foo2 = Foo()<br>print(foo1 is foo2)  </p><h3 id="83-简述-any-和-all-方法"><a href="#83-简述-any-和-all-方法" class="headerlink" title="83. 简述 any() 和 all() 方法"></a>83. 简述 any() 和 all() 方法</h3><p>答： any(x)：判断 x 对象是否为空对象，如果都为空、0、false，则返回 false，如果不都为空、0、false，则返回 true。 all(x)：如果 all(x) 参数 x 对象的所有元素不为 0、’’、False 或者 x 为空对象，则返回 True，否则返回 False。  </p><h3 id="84-filter-方法求出列表所有奇数并构造新列表，a-1-2-3-4-5-6-7-8-9-10"><a href="#84-filter-方法求出列表所有奇数并构造新列表，a-1-2-3-4-5-6-7-8-9-10" class="headerlink" title="84. filter 方法求出列表所有奇数并构造新列表，a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"></a>84. filter 方法求出列表所有奇数并构造新列表，a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]</h3><p>答  </p><p>a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]<br>print(list(filter(lambda x： x % 2 == 1, a)))  </p><p>其实现在不推荐使用 filter,map 等方法了，一般列表生成式就可以搞定了。  </p><h3 id="85-什么是猴子补丁？"><a href="#85-什么是猴子补丁？" class="headerlink" title="85. 什么是猴子补丁？"></a>85. 什么是猴子补丁？</h3><p>答： 猴子补丁（monkey patching)：在运行时动态修改模块、类或函数，通常是添加功能或修正缺陷。猴子补丁在代码运行时内存中）发挥作用，不会修改源码，因此只对当前运行的程序实例有效。因为猴子补丁破坏了封装，而且容易导致程序与补丁代码的实现细节紧密耦合，所以被视为临时的变通方案，不是集成代码的推荐方式。大概是下面这样的一个效果  </p><p>def post()：<br>print(“this is post”)<br>print(“想不到吧”)  </p><p>class Http()：<br>@classmethod<br>def get(self)：<br>    print(“this is get”)  </p><p>def main()：<br>Http.get=post #动态的修改了 get 原因的功能，  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>main()<br>Http.get()   </p><h3 id="86-在-Python-中是如何管理内存的？"><a href="#86-在-Python-中是如何管理内存的？" class="headerlink" title="86. 在 Python 中是如何管理内存的？"></a>86. 在 Python 中是如何管理内存的？</h3><p>答： 垃圾回收：Python 不像 C++，Java 等语言一样，他们可以不用事先声明变量类型而直接对变量进行赋值。对 Python 语言来讲，对象的类型和内存都是在运行时确定的。这也是为什么我们称 Python 语言为动态类型的原因（这里我们把动态类型可以简单的归结为对变量内存地址的分配是在运行时自动判断变量类型并对变量进行赋值）。  </p><p>引用计数：Python 采用了类似 Windows 内核对象一样的方式来对内存进行管理。每一个对象，都维护这一个对指向该对对象的引用的计数。当变量被绑定在一个对象上的时候，该变量的引用计数就是 1，(还有另外一些情况也会导致变量引用计数的增加)，系统会自动维护这些标签，并定时扫描，当某标签的引用计数变为 0 的时候，该对就会被回收。  </p><p>内存池机制 Python 的内存机制以金字塔行，1、2 层主要有操作系统进行操作  </p><p>第 0 层是 C 中的 malloc，free 等内存分配和释放函数进行操作  </p><p>第 1 层和第 2 层是内存池，有 Python 的接口函数 PyMem_Malloc 函数实现，当对象小于 256K 时有该层直接分配内存  </p><p>第 3 层是最上层，也就是我们对 Python 对象的直接操作  </p><p>在 C 中如果频繁的调用 malloc 与 free 时,是会产生性能问题的.再加上频繁的分配与释放小块的内存会产生内存碎片。Python 在这里主要干的工作有：  </p><pre><code>如果请求分配的内存在 1~256 字节之间就使用自己的内存管理系统,否则直接使用 malloc。  这里还是会调用 malloc 分配内存，但每次会分配一块大小为 256k 的大块内存。  </code></pre><p>经由内存池登记的内存到最后还是会回收到内存池，并不会调用 C 的 free 释放掉以便下次使用。对于简单的 Python 对象，例如数值、字符串，元组（tuple 不允许被更改)采用的是复制的方式(深拷贝?)，也就是说当将另一个变量 B 赋值给变量 A 时，虽然 A 和 B 的内存空间仍然相同，但当 A 的值发生变化时，会重新给 A 分配空间，A 和 B 的地址变得不再相同。  </p><h3 id="87-当退出-Python-时是否释放所有内存分配？"><a href="#87-当退出-Python-时是否释放所有内存分配？" class="headerlink" title="87. 当退出 Python 时是否释放所有内存分配？"></a>87. 当退出 Python 时是否释放所有内存分配？</h3><p>答：不是的，循环引用其他对象或引用自全局命名空间的对象的模块，在 Python 退出时并非完全释放。  </p><p>另外，也不会释放 c 库保留的内存部分<br>正则表达式  </p><h3 id="88-（1）使用正则表达式匹配出-lt-h1-gt-www-baidu-com中的地址（2）a-”张明-98-分”，用-re-sub，将-98-替换为-100"><a href="#88-（1）使用正则表达式匹配出-lt-h1-gt-www-baidu-com中的地址（2）a-”张明-98-分”，用-re-sub，将-98-替换为-100" class="headerlink" title="88. （1）使用正则表达式匹配出&lt;h1&gt;www.baidu.com中的地址（2）a=”张明 98 分”，用 re.sub，将 98 替换为 100"></a>88. （1）使用正则表达式匹配出<html>&lt;h1&gt;<a href="http://www.baidu.com/">www.baidu.com</a></h1></html>中的地址（2）a=”张明 98 分”，用 re.sub，将 98 替换为 100</h3><p>答： 第一问答案  </p><p>import re  </p><p>source = “<html><h1><a href="http://www.baidu.com/">www.baidu.com</a></h1></html>“<br>pat = re.compile(“<html><h1>(.*?)</h1></html>“)<br>print(pat.findall(source)[0])  </p><p>第二问答案  </p><p>import re<br>s = “张明 98 分”<br>print(re.sub(r”\d+”,”100”,s))  </p><h3 id="89-正则表达式匹配中-和-匹配区别？"><a href="#89-正则表达式匹配中-和-匹配区别？" class="headerlink" title="89. 正则表达式匹配中(.)和(.?)匹配区别？"></a>89. 正则表达式匹配中(.<em>)和(.</em>?)匹配区别？</h3><p>答：(.<em>) 为贪婪模式极可能多的匹配内容 ,(.</em>?) 为非贪婪模式又叫懒惰模式，一般匹配到结果就好，匹配字符的少为主，示例代码如下  </p><p>import re  </p><p>s = “<html><div>文本 1</div><div>文本 2</div></html>“  </p><p>pat1 = re.compile(r”&lt;div&gt;(.*?)&lt;/div&gt;”)<br>print(pat1.findall(s))  </p><p>pat2 = re.compile(r”&lt;div&gt;(.*)&lt;/div&gt;”)<br>print(pat2.findall(s))  </p><p>输出  </p><p>[‘文本 1’, ‘文本 2’]<br>[‘文本 1</div><div>文本 2’]  </p><h3 id="90-写一段匹配邮箱的正则表达式"><a href="#90-写一段匹配邮箱的正则表达式" class="headerlink" title="90. 写一段匹配邮箱的正则表达式"></a>90. 写一段匹配邮箱的正则表达式</h3><p>答：关于邮箱的匹配这个还真的是一个永恒的话题。  </p><p>电子邮件地址有统一的标准格式：用户名@服务器域名。用户名表示邮件信箱、注册名或信件接收者的用户标识，@符号后是你使用的邮件服务器的域名。@可以读成“at”，也就是“在”的意思。整个电子邮件地址可理解为网络中某台服务器上的某个用户的地址。  </p><p>用户名，可以自己选择。由字母 a～z(不区分大小写)、数字 0～9、点、减号或下划线组成；只能以数字或字母开头和结尾。<br>与你使用的网站有关，代表邮箱服务商。例如网易的有@163.com 新浪有@vip.sina.com 等。  </p><p>网上看到了各种各样的版本，都不确定用哪个，于是自己简单的总结了一个。大家有更好的欢迎留言。  </p><p>r”^[a-zA-Z0-9]+[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$”  </p><p>下面解释上面的表达式  </p><p>首先强调一点关于\w 的含义，\w 匹配英文字母和俄语字母或数字或下划线或汉字。<br>注意^[]和[^]的区别，[]表示字符集合，^[]表示已[]内的任意字符集开始，[^]表示。<br>^[a-zA-Z0-9]+：这里注意^[]和[^]的,第一个^表示已什么开头，第二个[]的^表示不等于[]内。所以这段表示以英文字母和数字开头，后面紧跟的+，限定其个数&gt;=1 个。<br>[a-zA-Z0-9.+-]+：表示匹配英文字母和数字开头以及.+-, 的任意一个字符，并限定其个数&gt;=1 个。为了考虑@前面可能出现.+-（但是不在开头出现）。<br>@就是邮箱必备符号了<br>@[a-zA-Z0-9-]+.：前面的不用说了，后面的.表示.转义了,也是必备符号。<br>[ a-zA-Z0-9-.]+：$符表示以什么结束,这里表示以英文字和数字或 -. 1 个或多个结尾。  </p><p>来个例子验证一波：  </p><p>import re<br>plt=re.compile(r”^[a-zA-Z0-9]+[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$”)<br>b=plt.findall(‘adas+fefe.we@qq.com.cn’)<br>print(b)  </p><p>网上找了个验证邮件地址的通用正则表达式（符合 RFC 5322 标准）  </p><p>(?：[a-z0-9!#$%&amp;’<em>+/=?^_<code>&#123;|&#125;~-]+(?：\.[a-z0-9!#$%&amp;&#39;*+/=?^_</code>{|}~-]+)</em>|”(?：[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\[\x01-\x09\x0b\x0c\x0e-\x7f])<em>“)@(?：(?：<a href="?%EF%BC%9A%5Ba-z0-9-%5D*%5Ba-z0-9%5D">a-z0-9</a>?.)+<a href="?%EF%BC%9A%5Ba-z0-9-%5D*%5Ba-z0-9%5D">a-z0-9</a>?|[(?：(?：25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?：25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]</em>[a-z0-9]：(?：[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\[\x01-\x09\x0b\x0c\x0e-\x7f])+)])  </p><p>其他内容  </p><h3 id="91-解释一下-Python-中-pass-语句的作用？"><a href="#91-解释一下-Python-中-pass-语句的作用？" class="headerlink" title="91. 解释一下 Python 中 pass 语句的作用？"></a>91. 解释一下 Python 中 pass 语句的作用？</h3><p>答：pass 实际上就是一个占位符，在写一个函数但是不确定里面写啥的时候，这个时候可以使用 pass。示例如下  </p><p>def foo()：<br>pass  </p><h3 id="92-简述你对-input-函数的理解"><a href="#92-简述你对-input-函数的理解" class="headerlink" title="92. 简述你对 input()函数的理解"></a>92. 简述你对 input()函数的理解</h3><p>答：在 Python3 中 input 函数可以接收用户输入的字符串。  </p><p>然后根据程序的需要转换成所需格式即可。  </p><h3 id="93-Python-中的-is-和"><a href="#93-Python-中的-is-和" class="headerlink" title="93. Python 中的 is 和=="></a>93. Python 中的 is 和==</h3><p>答：先说==它的作用是判断两个对象的值是否相同，然后说 is。is 表示的谁是谁，这也就意味着对象完全相等。我们知道一个对象有各自的内存地址和对应的值，当内存地址和值都相同的时候使用 is 可以得到结果 True。另外需要注意的下面两点特殊的情况。  </p><p>这些变量很可能在许多程序中使用。 通过池化这些对象，Python 可以防止对一致使用的对象进行内存分配调用。  </p><h3 id="1-介于数字-5-和-256-之间的整数"><a href="#1-介于数字-5-和-256-之间的整数" class="headerlink" title="1.介于数字-5 和 256 之间的整数"></a>1.介于数字-5 和 256 之间的整数</h3><h3 id="2-字符串仅包含字母、数字或下划线"><a href="#2-字符串仅包含字母、数字或下划线" class="headerlink" title="2.字符串仅包含字母、数字或下划线"></a>2.字符串仅包含字母、数字或下划线</h3><h3 id="94-Python-中的作用域"><a href="#94-Python-中的作用域" class="headerlink" title="94. Python 中的作用域"></a>94. Python 中的作用域</h3><p>答：  </p><p>Python 中，一个变量的作用域总是由在代码中被赋值的地方所决定  </p><p>当 Python 遇到一个变量的话它会按照这的顺序进行搜索  </p><p>本地作用域(Local)—&gt;当前作用域被嵌入的本地作用域(Enclosing locals)—&gt;全局/模块作用域(Global)—&gt;内置作用域(Built-in)  </p><h3 id="95-三元运算写法和应用场景？"><a href="#95-三元运算写法和应用场景？" class="headerlink" title="95. 三元运算写法和应用场景？"></a>95. 三元运算写法和应用场景？</h3><p>答：Python 中的三元运算又称三目运算，是对简单的条件语句的简写。 是一种比较 Pythonic 的学法，形式为：val = 1 if 条件成立 else 2 代码示例如下：  </p><p>a = 2<br>b = 5  </p><h1 id="普通写法"><a href="#普通写法" class="headerlink" title="普通写法"></a>普通写法</h1><p>if a &gt; b：<br>val = True<br>else：<br>val = False  </p><h1 id="改为三元运算符后"><a href="#改为三元运算符后" class="headerlink" title="改为三元运算符后"></a>改为三元运算符后</h1><p>val = a if a &gt; b else b<br>print(val)  # 5  </p><h3 id="96-了解-enumerate-么？"><a href="#96-了解-enumerate-么？" class="headerlink" title="96. 了解 enumerate 么？"></a>96. 了解 enumerate 么？</h3><p>答：enumerate 可以在迭代一个对象的时候，同时获取当前对象的索引和值。 代码示例如下  </p><p>from string import ascii_lowercase  </p><p>s = ascii_lowercase  </p><p>for index, value in enumerate(s)：<br>print(index, value)  </p><h3 id="97-列举-5-个-Python-中的标准模块"><a href="#97-列举-5-个-Python-中的标准模块" class="headerlink" title="97. 列举 5 个 Python 中的标准模块"></a>97. 列举 5 个 Python 中的标准模块</h3><p>答： pathlib：路径操作模块，比 os 模块拼接方便。 urllib：网络请求模块，包括对 url 的结构解析。 asyncio： Python 的异步库，基于事件循环的协程模块。 re：正则表达式模块。 itertools：提供了操作生成器的一些模块。  </p><h3 id="98-如何在函数中设置一个全局变量"><a href="#98-如何在函数中设置一个全局变量" class="headerlink" title="98. 如何在函数中设置一个全局变量"></a>98. 如何在函数中设置一个全局变量</h3><p>答：  </p><h1 id="通过使用-global-对全局变量进行修改。"><a href="#通过使用-global-对全局变量进行修改。" class="headerlink" title="通过使用 global 对全局变量进行修改。"></a>通过使用 global 对全局变量进行修改。</h1><p>n = 0<br>def foo()：<br>global n<br>n = 100<br>foo()<br>print(n)<br>x = 0  </p><p>之前我在视频教程中对这块做了个讲解，具体点击下方链接 https：//<a href="http://www.bilibili.com/video/av50865713">www.bilibili.com/video/av50865713</a>  </p><h3 id="99-pathlib-的用法举例"><a href="#99-pathlib-的用法举例" class="headerlink" title="99. pathlib 的用法举例"></a>99. pathlib 的用法举例</h3><p>答：pathlib 可以对文件以及文件的其他属性进行操作。比较喜欢的一点是路径拼接符”/“的使用，之前在公众号中写过 pathlib 一些其他的用法这里就不一一例举了。  </p><h3 id="100-Python-中的异常处理，写一个简单的应用场景"><a href="#100-Python-中的异常处理，写一个简单的应用场景" class="headerlink" title="100. Python 中的异常处理，写一个简单的应用场景"></a>100. Python 中的异常处理，写一个简单的应用场景</h3><p>答： 比如在计算除法中出现为 0 的情况出现异常  </p><p>try：<br>1 / 0<br>except ZeroDivisionError as e：<br>print(e.args)  </p><h3 id="101-Python-中递归的最大次数，那如何突破呢？"><a href="#101-Python-中递归的最大次数，那如何突破呢？" class="headerlink" title="101. Python 中递归的最大次数，那如何突破呢？"></a>101. Python 中递归的最大次数，那如何突破呢？</h3><p>答：Python 有递归次数限制，默认最大次数为 1000。通过下面的代码可以突破这个限制  </p><p>import sys<br>sys.setrecursionlimit(1500) # set the maximum depth as 1500  </p><p>另外需要注意的是 sys.setrecursionlimit() 只是修改解释器在解释时允许的最大递归次数，此外，限制最大递归次数的还和操作系统有关。  </p><h3 id="102-什么是面向对象的-mro"><a href="#102-什么是面向对象的-mro" class="headerlink" title="102. 什么是面向对象的 mro"></a>102. 什么是面向对象的 mro</h3><p>答：Python 是支持面向对象编程的，同时也是支持多重继承的。一般我们通过调用类对象的 mro()方法获取其继承关系。  </p><h3 id="103-isinstance-作用以及应用场景？"><a href="#103-isinstance-作用以及应用场景？" class="headerlink" title="103. isinstance 作用以及应用场景？"></a>103. isinstance 作用以及应用场景？</h3><p>答：isinstance 是判断一个对象是否为另一个对象的子类的，例如我们知道在 Python3 中 bool 类型其实是 int 的子类，所以我们可以对其检测。  </p><p>print(isinstance(True,int))  </p><h3 id="104-什么是断言？应用场景？"><a href="#104-什么是断言？应用场景？" class="headerlink" title="104. 什么是断言？应用场景？"></a>104. 什么是断言？应用场景？</h3><p>答：在 Python 中是断言语句 assert 实现此功能，一般在表达式为 True 的情况下，程序才能通过。  </p><p>#author：陈祥安<br>#公众号：Python 学习开发  </p><p>#assert（）方法，断言成功，则程序继续执行，断言失败，则程序报错  </p><h1 id="断言能够帮助别人或未来的你理解代码，"><a href="#断言能够帮助别人或未来的你理解代码，" class="headerlink" title="断言能够帮助别人或未来的你理解代码，"></a>断言能够帮助别人或未来的你理解代码，</h1><h1 id="找出程序中逻辑不对的地方。一方面，"><a href="#找出程序中逻辑不对的地方。一方面，" class="headerlink" title="找出程序中逻辑不对的地方。一方面，"></a>找出程序中逻辑不对的地方。一方面，</h1><h1 id="断言会提醒你某个对象应该处于何种状态，"><a href="#断言会提醒你某个对象应该处于何种状态，" class="headerlink" title="断言会提醒你某个对象应该处于何种状态，"></a>断言会提醒你某个对象应该处于何种状态，</h1><h1 id="另一方面，如果某个时候断言为假，"><a href="#另一方面，如果某个时候断言为假，" class="headerlink" title="另一方面，如果某个时候断言为假，"></a>另一方面，如果某个时候断言为假，</h1><h1 id="会抛出-AssertionError-异常，很有可能终止程序。"><a href="#会抛出-AssertionError-异常，很有可能终止程序。" class="headerlink" title="会抛出 AssertionError 异常，很有可能终止程序。"></a>会抛出 AssertionError 异常，很有可能终止程序。</h1><p>def foo(a)：<br>assert a==2,Exception(“不等于 2”)<br>print(“ok”,a)  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>foo(1)  </p><h3 id="105-lambda-表达式格式以及应用场景？"><a href="#105-lambda-表达式格式以及应用场景？" class="headerlink" title="105. lambda 表达式格式以及应用场景？"></a>105. lambda 表达式格式以及应用场景？</h3><p>答：lambda 表达式其实就是一个匿名函数,在函数编程中经常作为参数使用。 例子如下  </p><p>a = [(‘a’,1),(‘b’,2),(‘c’,3),(‘d’,4)]<br>a_1 = list(map(lambda x：x[0],a))  </p><h3 id="106-新式类和旧式类的区别"><a href="#106-新式类和旧式类的区别" class="headerlink" title="106. 新式类和旧式类的区别"></a>106. 新式类和旧式类的区别</h3><p>答：Python 2.x 中默认都是经典类，只有显式继承了 object 才是新式类，Python 3.x 中默认都是新式类，经典类被移除，不必显式的继承 object。 新式类都从 object 继承，经典类不需要。 新式类的 MRO(method resolution order 基类搜索顺序)算法采用 C3 算法广度优先搜索，而旧式类的 MRO 算法是采用深度优先搜索。 新式类相同父类只执行一次构造函数，经典类重复执行多次。  </p><h3 id="107-dir-是干什么用的？"><a href="#107-dir-是干什么用的？" class="headerlink" title="107. dir()是干什么用的？"></a>107. dir()是干什么用的？</h3><p>答：当在使用某一个对象不知道有哪些属性或者方法可以使用时，此时可以通过 dir() 方法进行查看。  </p><h3 id="108-一个包里有三个模块，demo1-py、demo2-py、demo3-py，但使用-from-tools-import-导入模块时，如何保证只有-demo1、demo3-被导入了。"><a href="#108-一个包里有三个模块，demo1-py、demo2-py、demo3-py，但使用-from-tools-import-导入模块时，如何保证只有-demo1、demo3-被导入了。" class="headerlink" title="108. 一个包里有三个模块，demo1.py、demo2.py、demo3.py，但使用 from tools import *导入模块时，如何保证只有 demo1、demo3 被导入了。"></a>108. 一个包里有三个模块，demo1.py、demo2.py、demo3.py，但使用 from tools import *导入模块时，如何保证只有 demo1、demo3 被导入了。</h3><p>答： 增加_init_.py 文件，并在文件中增加：  </p><p><strong>all</strong> = [‘demo1’,’demo3’]  </p><h3 id="109-列举-5-个-Python-中的异常类型以及其含义"><a href="#109-列举-5-个-Python-中的异常类型以及其含义" class="headerlink" title="109. 列举 5 个 Python 中的异常类型以及其含义"></a>109. 列举 5 个 Python 中的异常类型以及其含义</h3><p>答：  </p><p>AttributeError 对象没有这个属性  </p><p>NotImplementedError 尚未实现的方法  </p><p>StopIteration 迭代器没有更多的值  </p><p>TypeError 对类型无效的操作  </p><p>IndentationError 缩进错误  </p><h3 id="110-copy-和-deepcopy-的区别是什么？"><a href="#110-copy-和-deepcopy-的区别是什么？" class="headerlink" title="110. copy 和 deepcopy 的区别是什么？"></a>110. copy 和 deepcopy 的区别是什么？</h3><p>答： copy.copy()浅拷贝，只拷贝父对象，不会拷贝对象的内部的子对象。 copy.deepcopy()深拷贝，拷贝对象及其子对象。  </p><h3 id="111-代码中经常遇到的-args-kwargs-含义及用法。"><a href="#111-代码中经常遇到的-args-kwargs-含义及用法。" class="headerlink" title="111. 代码中经常遇到的*args, **kwargs 含义及用法。"></a>111. 代码中经常遇到的*args, **kwargs 含义及用法。</h3><p>答： 在函数定义中使用 *args 和**kwargs 传递可变长参数。 *args 用来将参数打包成 tuple 给函数体调用。 **kwargs 打包关键字参数成 dict 给函数体调用。  </p><h3 id="112-Python-中会有函数或成员变量包含单下划线前缀和结尾，和双下划线前缀结尾，区别是什么"><a href="#112-Python-中会有函数或成员变量包含单下划线前缀和结尾，和双下划线前缀结尾，区别是什么" class="headerlink" title="112. Python 中会有函数或成员变量包含单下划线前缀和结尾，和双下划线前缀结尾，区别是什么?"></a>112. Python 中会有函数或成员变量包含单下划线前缀和结尾，和双下划线前缀结尾，区别是什么?</h3><p>答： “单下划线” 开始的成员变量叫做保护变量，意思是只有类对象和子类对象自己能访问到这些变量； “双下划线” 开始的是私有成员，意思是只有类对象自己能访问，连子类对象也不能访问到这个数据。  </p><p>以单下划线开头（_foo）的代表不能直接访问的类属性，需通过类提供的接口进行访问，不能用“from xxx import *”而导入；以双下划线开头的（__foo）代表类的私有成员；  </p><p>以双下划线开头和结尾的（_foo）代表 Python 里特殊方法专用的标识，如 _init（）代表类的构造函数。  </p><p>代码示例  </p><p>class Person：<br>“””docstring for ClassName”””<br>def <strong>init</strong>(self)：<br>   self.__age = 12<br>   self._sex = 12<br>def _sex(self)：<br>    return “男”<br>def set_age(self,age)：<br>    self.__age = age  </p><p>def get_age(self)：<br>    return self.__age     </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>p=Person()<br>print(p._sex)<br>#print(p.__age)<br>#Python 自动将__age 解释成 _Person__age,于是我们用 _Person__age 访问，这次成功。<br>print(p._Person__age)  </p><h3 id="113-w、a-、wb-文件写入模式的区别"><a href="#113-w、a-、wb-文件写入模式的区别" class="headerlink" title="113. w、a+、wb 文件写入模式的区别"></a>113. w、a+、wb 文件写入模式的区别</h3><p>答： w 表示写模式支持写入字符串，如果文件存在则覆盖。 a+ 和 w 的功能类型不过如果文件存在的话内容不会覆盖而是追加。 wb 是写入二进制字节类型的数据。  </p><h3 id="114-举例-sort-和-sorted-的区别"><a href="#114-举例-sort-和-sorted-的区别" class="headerlink" title="114. 举例 sort 和 sorted 的区别"></a>114. 举例 sort 和 sorted 的区别</h3><p>答： 相同之处 sort 和 sorted 都可以对列表元素排序，sort() 与 sorted() 的不同在于，sort 是在原位重新排列列表，而 sorted() 是产生一个新的列表。 sort 是应用在 list 上的方法，sorted 可以对所有可迭代的对象进行排序操作。  </p><p>list 的 sort 方法返回的是对已经存在的列表进行操作，而内建函数 sorted 方法返回的是一个新的 list，而不是在原来的基础上进行的操作。  </p><h3 id="115-什么是负索引？"><a href="#115-什么是负索引？" class="headerlink" title="115. 什么是负索引？"></a>115. 什么是负索引？</h3><p>答：负索引一般表示的是从后面取元素。  </p><h3 id="116-pprint-模块是干什么的？"><a href="#116-pprint-模块是干什么的？" class="headerlink" title="116. pprint 模块是干什么的？"></a>116. pprint 模块是干什么的？</h3><p>答：pprint 是 print 函数的美化版，可以通过 import pprint 导入。示例如下  </p><p>import pprint<br>pprint.pprint(“this is pprint”)  </p><h3 id="117-解释一下-Python-中的赋值运算符"><a href="#117-解释一下-Python-中的赋值运算符" class="headerlink" title="117. 解释一下 Python 中的赋值运算符"></a>117. 解释一下 Python 中的赋值运算符</h3><p>答：通过下面的代码列举出所有的赋值运算符  </p><p>a=7<br>a+=1<br>print(a)<br>a-=1<br>print(a)<br>a*=2<br>print(a)<br>a/=2<br>print(a)<br>a**=2<br>print(a)<br>a//=3<br>print(a)<br>a%=4<br>print(a)  </p><h3 id="118-解释一下-Python-中的逻辑运算符"><a href="#118-解释一下-Python-中的逻辑运算符" class="headerlink" title="118. 解释一下 Python 中的逻辑运算符"></a>118. 解释一下 Python 中的逻辑运算符</h3><p>答：Python 中有三个逻辑运算符：and、or、not  </p><p>print(False and True) #False<br>print(7&lt;7 or True) #True<br>print(not 2==2) #False  </p><h3 id="119-讲讲-Python-中的位运算符"><a href="#119-讲讲-Python-中的位运算符" class="headerlink" title="119. 讲讲 Python 中的位运算符"></a>119. 讲讲 Python 中的位运算符</h3><p>答：按位运算符是把数字看作二进制来进行计算的。Python 中的按位运算法则如下：  </p><p>下表中变量 a 为 60，b 为 13，二进制格式如下：  </p><p>a = 0011 1100<br>b = 0000 1101  </p><hr><p>a&amp;b = 0000 1100<br>a|b = 0011 1101<br>a^b = 0011 0001<br>~a  = 1100 0011  </p><p>enter image description here  </p><h3 id="120-在-Python-中如何使用多进制数字？"><a href="#120-在-Python-中如何使用多进制数字？" class="headerlink" title="120. 在 Python 中如何使用多进制数字？"></a>120. 在 Python 中如何使用多进制数字？</h3><p>答： 我们在 Python 中，除十进制外还可以使用二进制、八进制和十六进制  </p><p>二进制数字由 0 和 1 组成，我们使用 0b 或 0B 前缀表示二进制数  </p><p>print(int(0b1010))#10  </p><p>使用 bin()函数将一个数字转换为它的二进制形式  </p><p>print(bin(0xf))#0b1111  </p><p>八进制数由数字 0-7 组成，用前缀 0o 或 0O 表示 8 进制数  </p><p>print(oct(8))#0o10  </p><p>十六进数由数字 0-15 组成，用前缀 0x 或者 0X 表示 16 进制数  </p><p>print(hex(16))#0x10<br>print(hex(15))#0xf  </p><h3 id="121-怎样声明多个变量并赋值？"><a href="#121-怎样声明多个变量并赋值？" class="headerlink" title="121. 怎样声明多个变量并赋值？"></a>121. 怎样声明多个变量并赋值？</h3><p>答：Python 是支持多个变量赋值的，代码示例如下  </p><p>#对变量 a,b,c 声明并赋值<br>a,b,c = 1,2,3  </p><p>算法和数据结构  </p><h3 id="122-已知："><a href="#122-已知：" class="headerlink" title="122. 已知："></a>122. 已知：</h3><p>AList = [1,2,3]<br>BSet = {1,2,3}  </p><p>(1) 从 AList 和 BSet 中 查找 4，最坏时间复杂度哪个大？ (2) 从 AList 和 BSet 中 插入 4，最坏时间复杂度哪个大？  </p><p>答： (1) 对于查找，列表和集合的最坏时间复杂度都是 O(n)，所以一样的。 (2) 列表操作插入的最坏时间复杂度为 o(n),集合为 o(1)，所以 Alist 大。 set 是哈希表所以操作的复杂度基本上都是 o(1)。  </p><h3 id="123-用-Python-实现一个二分查找的函数"><a href="#123-用-Python-实现一个二分查找的函数" class="headerlink" title="123. 用 Python 实现一个二分查找的函数"></a>123. 用 Python 实现一个二分查找的函数</h3><p>答：  </p><p>def binary_search(arr, target)：<br>n = len(arr)<br>left = 0<br>right = n-1<br>while left &lt;= right ：<br>    mid = (left + right)//2<br>    if arr[mid] &lt; target：<br>        left = mid + 1<br>    elif arr[mid] &gt; target：<br>        right = mid - 1<br>    else：<br>        print(f”index：{mid},value：{arr[mid]}”)<br>        return True<br>return False  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br> l = [1,3,4,5,6,7,8]<br> binary_search(l,8)     </p><h3 id="124-Python-单例模式的实现方法"><a href="#124-Python-单例模式的实现方法" class="headerlink" title="124. Python 单例模式的实现方法"></a>124. Python 单例模式的实现方法</h3><p>答：实现单例模式的方法有多种，之前再说元类的时候用 call 方法实现了一个单例模式，另外 Python 的模块就是一个天然的单例模式，这里我们使用 new 关键字来实现一个单例模式。  </p><p>“””<br>通过 new 函数实现简单的单例模式。<br>“””<br>class Book：<br>def <strong>new</strong>(cls, title)：<br>    if not hasattr(cls, “_ins”)：<br>        cls._ins = super().<strong>new</strong>(cls)<br>    print(‘in <strong>new</strong>‘)<br>    return cls._ins  </p><p>def <strong>init</strong>(self, title)：<br>    print(‘in <strong>init</strong>‘)<br>    super().<strong>init</strong>()<br>    self.title = title  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>b = Book(‘The Spider Book’)<br>b2 = Book(‘The Flask Book’)<br>print(id(b))<br>print(id(b2))<br>print(b.title)<br>print(b2.title)  </p><h3 id="125-使用-Python-实现一个斐波那契数列"><a href="#125-使用-Python-实现一个斐波那契数列" class="headerlink" title="125. 使用 Python 实现一个斐波那契数列"></a>125. 使用 Python 实现一个斐波那契数列</h3><p>答： 斐波那契数列：数列从第 3 项开始，每一项都等于前两项之和。  </p><p>def fibonacci(num)：<br>“””<br>获取指定位数的列表<br>：param num：<br>：return：<br>“””<br>a, b = 0, 1<br>l = []<br>for i in range(num)：<br>    a, b = b, a + b<br>    l.append(b)<br>return l  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>print(fibonacci(10))  </p><h3 id="126-找出列表中的重复数字"><a href="#126-找出列表中的重复数字" class="headerlink" title="126. 找出列表中的重复数字"></a>126. 找出列表中的重复数字</h3><p>答：  </p><p>“””<br>从头扫到尾，只要当前元素值与下标不同，就做一次判断,numbers[i]与 numbers[numbers[i]]，<br>相等就认为找到了重复元素，返回 true,否则就交换两者，继续循环。直到最后还没找到认为没找到重复元素。<br>“””  </p><h1 id="coding：utf-8"><a href="#coding：utf-8" class="headerlink" title="-- coding：utf-8 --"></a>-<em>- coding：utf-8 -</em>-</h1><p>class Solution:<br>def duplicate(self, numbers):<br>    “””  </p><pre><code>:param numbers:  :return:  &quot;&quot;&quot;  if numbers is None or len(numbers) &lt;= 1:      return False  use_set = set()  duplication = &#123;&#125;  for index, value in enumerate(numbers):      if value not in use_set:          use_set.add(value)      else:          duplication[index] = value  return duplication  </code></pre><p>if <strong>name</strong> == ‘<strong>main</strong>‘:<br>s = Solution()<br>d = s.duplicate([1, 2, -3, 4, 4, 95, 95, 5, 2, 2, -3, 7, 7, 5])<br>print(d)  </p><h3 id="127-找出列表中的单个数字"><a href="#127-找出列表中的单个数字" class="headerlink" title="127. 找出列表中的单个数字"></a>127. 找出列表中的单个数字</h3><p>答：  </p><p>def find_single(l ：list)：<br>result = 0<br>for v in l：<br>    result ^= v<br>if result == 0：<br>    print(“没有落单元素”)<br>else：<br>    print(“落单元素” ,result)  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>l = [1,2,3,4,5,6,2,3,4,5,6]<br>find_single(l)          </p><h3 id="128-写一个冒泡排序"><a href="#128-写一个冒泡排序" class="headerlink" title="128. 写一个冒泡排序"></a>128. 写一个冒泡排序</h3><p>答：  </p><p>“””<br>冒泡排序<br>“””<br>def bubble_sort(arr)：<br>n = len(arr)<br>for i in range(n - 1)：<br>    for j in range(n - i - 1)：<br>        if arr[j] &gt; arr[j + 1]：<br>            arr[j], arr[j + 1] = arr[j + 1], arr[j]  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>l = [1, 2, 3, 4, 5, 55, 6, 3, 4, 5, 6]<br>bubble_sort(l)<br>print(l)  </p><h3 id="129-写一个快速排序"><a href="#129-写一个快速排序" class="headerlink" title="129. 写一个快速排序"></a>129. 写一个快速排序</h3><p>答：  </p><p>“””<br>快速排序<br>“””  </p><p>def quick_sort(arr, first, last)：<br>if first &gt;= last：<br>    return<br>mid_value = arr[first]<br>low = first<br>high = last  </p><p>while low &lt; high：<br>    while low &lt; high and arr[high] &gt;= mid_value：<br>        high -= 1  # 游标左移<br>    arr[low] = arr[high]  </p><pre><code>while low &lt; high and arr[low] &lt; mid_value：      low += 1  arr[high] = arr[low]  arr[low] = mid_value  </code></pre><p>quick_sort(arr, first, low - 1)<br>quick_sort(arr, low + 1, last)  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>l = [1, 2, 3, 4, 5, 55, 6, 3, 4, 5, 6]<br>quick_sort(l, 0, len(l) - 1)<br>print(l)  </p><h3 id="130-写一个拓扑排序"><a href="#130-写一个拓扑排序" class="headerlink" title="130. 写一个拓扑排序"></a>130. 写一个拓扑排序</h3><p>答：  </p><p>“””<br>拓扑排序<br>对应于该图的拓扑排序。每一个有向无环图都至少存在一种拓扑排序。  </p><p>“””<br>import pysnooper<br>from typing import Mapping  </p><p>@pysnooper.snoop()<br>def topological_sort(graph： Mapping)：  </p><h1 id="in-degrees-‘a’：-0-‘b’：-0-‘c’：-0-‘d’：-0-‘e’：-0-‘f’：-0"><a href="#in-degrees-‘a’：-0-‘b’：-0-‘c’：-0-‘d’：-0-‘e’：-0-‘f’：-0" class="headerlink" title="in_degrees = {‘a’： 0, ‘b’： 0, ‘c’： 0, ‘d’： 0, ‘e’： 0, ‘f’： 0}"></a>in_degrees = {‘a’： 0, ‘b’： 0, ‘c’： 0, ‘d’： 0, ‘e’： 0, ‘f’： 0}</h1><p>in_degrees = dict((u, 0) for u in graph)<br>for u in graph：<br>    for v in graph[u]：  # 根据键找出值也就是下级节点<br>        in_degrees[v] += 1  # 对获取到的下级节点的入度加 1  </p><h1 id="循环结束之后的结果：-‘a’：-0-‘b’：-1-‘c’：-1-‘d’：-2-‘e’：-1-‘f’：-4"><a href="#循环结束之后的结果：-‘a’：-0-‘b’：-1-‘c’：-1-‘d’：-2-‘e’：-1-‘f’：-4" class="headerlink" title="循环结束之后的结果： {‘a’： 0, ‘b’： 1, ‘c’： 1, ‘d’： 2, ‘e’： 1, ‘f’： 4}"></a>循环结束之后的结果： {‘a’： 0, ‘b’： 1, ‘c’： 1, ‘d’： 2, ‘e’： 1, ‘f’： 4}</h1><p>Q = [u for u in graph if in_degrees[u] == 0]  # 入度为 0 的节点<br>in_degrees_zero = []<br>while Q：<br>    u = Q.pop()  # 默认从最后一个移除<br>    in_degrees_zero.append(u)  # 存储入度为 0 的节点<br>    for v in graph[u]：<br>        in_degrees[v] -= 1  # 删除入度为 0 的节点，以及移除其指向<br>        if in_degrees[v] == 0：<br>            Q.append(v)<br>return in_degrees_zero  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：  </p><h1 id="用字典的键值表示图的节点之间的关系，键当前节点。值是后续节点。"><a href="#用字典的键值表示图的节点之间的关系，键当前节点。值是后续节点。" class="headerlink" title="用字典的键值表示图的节点之间的关系，键当前节点。值是后续节点。"></a>用字典的键值表示图的节点之间的关系，键当前节点。值是后续节点。</h1><p>graph_dict = {<br>    ‘a’： ‘bf’,  # 表示 a 指向 b 和 f<br>    ‘b’： ‘cdf’,<br>    ‘c’： ‘d’,<br>    ‘d’： ‘ef’,<br>    ‘e’： ‘f’,<br>    ‘f’： ‘’<br>}  </p><p>t = topological_sort(graph_dict)<br>print(t)  </p><h3 id="131-Python-实现一个二进制计算"><a href="#131-Python-实现一个二进制计算" class="headerlink" title="131. Python 实现一个二进制计算"></a>131. Python 实现一个二进制计算</h3><p>答：  </p><p>“””<br>二进制加法<br>“””<br>def binary_add(a： str, b： str)：<br>return bin(int(a, 2) + int(b, 2))[2：]  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>num1 = input(“输入第一个数，二进制格式：\n”)<br>num2 = input(“输入第二个数，二进制格式：\n”)<br>print(binary_add(num1, num2))  </p><h3 id="132-有一组“-”和“-”符号，要求将“-”排到左边，“-”排到右边，写出具体的实现方法。"><a href="#132-有一组“-”和“-”符号，要求将“-”排到左边，“-”排到右边，写出具体的实现方法。" class="headerlink" title="132. 有一组“+”和“-”符号，要求将“+”排到左边，“-”排到右边，写出具体的实现方法。"></a>132. 有一组“+”和“-”符号，要求将“+”排到左边，“-”排到右边，写出具体的实现方法。</h3><p>答：  </p><p>“””<br>有一组“+”和“-”符号，要求将“+”排到左边，“-”排到右边，写出具体的实现方法。  </p><p>如果让+等于 0，-等于 1 不就是排序了么。<br>“””<br>from collections import deque<br>from timeit import Timer  </p><p>s = “++++++—-+++—-“  </p><h1 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h1><p>def func1()：<br>new_s = s.replace(“+”, “0”).replace(“-“, “1”)<br>result = “”.join(sorted(new_s)).replace(“0”, “+”).replace(“1”, “-“)<br>return result  </p><h1 id="方法二"><a href="#方法二" class="headerlink" title="方法二"></a>方法二</h1><p>def func2()：<br>q = deque()<br>left = q.appendleft<br>right = q.append<br>for i in s：<br>    if i == “+”：<br>        left(“+”)<br>    elif i == “-“：<br>        right(“-“)  </p><p>def func3()：<br>data = list(s)<br>start_index = 0<br>end_index = 0<br>count = len(s)<br>while start_index + end_index &lt; count：<br>    if data[start_index] == ‘-‘：<br>        data[start_index], data[count - end_index - 1] = data[count - end_index - 1], data[start_index]<br>        end_index += 1<br>    else：<br>        start_index += 1<br>return “”.join(data)  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>timer1 = Timer(“func1()”, “from <strong>main</strong> import func1”)<br>print(“func1”, timer1.timeit(1000000))<br>timer2 = Timer(“func2()”, “from <strong>main</strong> import func2”)<br>print(“func2”, timer2.timeit(1000000))<br>timer3 = Timer(“func3()”, “from <strong>main</strong> import func3”)<br>print(“func3”, timer3.timeit(1000000))  </p><h1 id="1000000-测试结果"><a href="#1000000-测试结果" class="headerlink" title="1000000 测试结果"></a>1000000 测试结果</h1><h1 id="func1-1-39003764"><a href="#func1-1-39003764" class="headerlink" title="func1 1.39003764"></a>func1 1.39003764</h1><h1 id="func2-1-593012875"><a href="#func2-1-593012875" class="headerlink" title="func2 1.593012875"></a>func2 1.593012875</h1><h1 id="func3-3-3487415590000005"><a href="#func3-3-3487415590000005" class="headerlink" title="func3 3.3487415590000005"></a>func3 3.3487415590000005</h1><h1 id="func1-的方式最优，其次是-func2"><a href="#func1-的方式最优，其次是-func2" class="headerlink" title="func1 的方式最优，其次是 func2"></a>func1 的方式最优，其次是 func2</h1><h3 id="133-单链表反转"><a href="#133-单链表反转" class="headerlink" title="133. 单链表反转"></a>133. 单链表反转</h3><p>答：  </p><p>“””<br>单链表反转<br>“””  </p><p>class Node：<br>def <strong>init</strong>(self, val=None)：<br>    self.val = val<br>    self.next = None  </p><p>class SingleLinkList：<br>def <strong>init</strong>(self, head=None)：<br>    “””链表的头部”””<br>    self._head = head  </p><p>def add(self, val： int)：<br>    “””<br>    给链表添加元素<br>    ：param val： 传过来的数字<br>    ：return：<br>    “””<br>    # 创建一个节点<br>    node = Node(val)<br>    if self._head is None：<br>        self._head = node<br>    else：<br>        cur = self._head<br>        while cur.next is not None：<br>            cur = cur.next  # 移动游标<br>        cur.next = node  # 如果 next 后面没了证明以及到最后一个节点了  </p><p>def traversal(self)：<br>    if self._head is None：<br>        return<br>    else：<br>        cur = self._head<br>        while cur is not None：<br>            print(cur.val)<br>            cur = cur.next  </p><p>def size(self)：<br>    “””<br>    获取链表的大小<br>    ：return：<br>    “””<br>    count = 0<br>    if self._head is None：<br>        return count<br>    else：<br>        cur = self._head<br>        while cur is not None：<br>            count += 1<br>            cur = cur.next<br>        return count  </p><p>def reverse(self)：<br>    “””<br>    单链表反转<br>    思路：<br>    让 cur.next 先断开即指向 none，指向设定 pre 游标指向断开的元素，然后<br>    cur.next 指向断开的元素，再把开始 self._head 再最后一个元素的时候.<br>    ：return：<br>    “””<br>    if self._head is None or self.size() == 1：<br>        return<br>    else：<br>        pre = None<br>        cur = self._head<br>        while cur is not None：<br>            post = cur.next<br>            cur.next = pre<br>            pre = cur<br>            cur = post<br>        self._head = pre  # 逆向后的头节点  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>single_link = SingleLinkList()<br>single_link.add(3)<br>single_link.add(5)<br>single_link.add(6)<br>single_link.add(7)<br>single_link.add(8)<br>print(“对链表进行遍历”)<br>single_link.traversal()<br>print(f”size：{single_link.size()}”)<br>print(“对链表进行逆向操作之后”)<br>single_link.reverse()<br>single_link.traversal()  </p><h3 id="134-交叉链表求交点"><a href="#134-交叉链表求交点" class="headerlink" title="134. 交叉链表求交点"></a>134. 交叉链表求交点</h3><p>答：  </p><h1 id="Definition-for-singly-linked-list"><a href="#Definition-for-singly-linked-list" class="headerlink" title="Definition for singly-linked list."></a>Definition for singly-linked list.</h1><p>class ListNode：<br>def <strong>init</strong>(self, x)：<br>    self.val = x<br>    self.next = None  </p><p>class Solution：<br>def getIntersectionNode(self, headA, headB)：<br>    “””<br>    ：tye head1, head1： ListNode<br>    ：rtye： ListNode<br>    “””<br>    if headA is not None and headB is not None：<br>        cur1, cur2 = headA, headB  </p><pre><code>    while cur1 != cur2：          cur1 = cur1.next if cur1 is not None else headA          cur2 = cur2.next if cur2 is not None else headB      return cur1  </code></pre><p>cur1、cur2，2 个指针的初始位置是链表 headA、headB 头结点，cur1、cur2 两个指针一直往后遍历。 直到 cur1 指针走到链表的末尾，然后 cur1 指向 headB； 直到 cur2 指针走到链表的末尾，然后 cur2 指向 headA； 然后再继续遍历； 每次 cur1、cur2 指向 None，则将 cur1、cur2 分别指向 headB、headA。 循环的次数越多，cur1、cur2 的距离越接近，直到 cur1 等于 cur2。则是两个链表的相交点。  </p><h3 id="135-用队列实现栈"><a href="#135-用队列实现栈" class="headerlink" title="135. 用队列实现栈"></a>135. 用队列实现栈</h3><p>答： 下面代码分别使用 1 个队列和 2 个队列实现了栈。  </p><p>from queue import Queue  </p><p>#使用 2 个队列实现<br>class MyStack：  </p><p>def <strong>init</strong>(self)：<br>    “””<br>    Initialize your data structure here.<br>    “””<br>    # q1 作为进栈出栈，q2 作为中转站<br>    self.q1 = Queue()<br>    self.q2 = Queue()  </p><p>def push(self, x)：<br>    “””<br>    Push element x onto stack.<br>    ：type x： int<br>    ：rtype： void<br>    “””<br>    self.q1.put(x)  </p><p>def pop(self)：<br>    “””<br>    Removes the element on top of the stack and returns that element.<br>    ：rtype： int<br>    “””  </p><pre><code>while self.q1.qsize() &gt; 1：      self.q2.put(self.q1.get())  # 将 q1 中除尾元素外的所有元素转到 q2 中  if self.q1.qsize() == 1：      res = self.q1.get()  # 弹出 q1 的最后一个元素      self.q1, self.q2 = self.q2, self.q1  # 交换 q1,q2      return res  </code></pre><p>def top(self)：<br>    “””<br>    Get the top element.<br>    ：rtype： int<br>    “””<br>    while self.q1.qsize() &gt; 1：<br>        self.q2.put(self.q1.get())  # 将 q1 中除尾元素外的所有元素转到 q2 中<br>    if self.q1.qsize() == 1：<br>        res = self.q1.get()  # 弹出 q1 的最后一个元素<br>        self.q2.put(res)  # 与 pop 唯一不同的是需要将 q1 最后一个元素保存到 q2 中<br>        self.q1, self.q2 = self.q2, self.q1  # 交换 q1,q2<br>        return res  </p><p>def empty(self)：<br>    “””<br>    Returns whether the stack is empty.<br>    ：rtype： bool<br>    “””<br>    return not bool(self.q1.qsize() + self.q2.qsize())  # 为空返回 True，不为空返回 False  </p><p>#使用 1 个队列实现<br>class MyStack2(object)：  </p><p>def <strong>init</strong>(self)：<br>    “””<br>    Initialize your data structure here.<br>    “””<br>    self.sq1 = Queue()  </p><p>def push(self, x)：<br>    “””<br>    Push element x onto stack.<br>    ：type x： int<br>    ：rtype： void<br>    “””<br>    self.sq1.put(x)  </p><p>def pop(self)：<br>    “””<br>    Removes the element on top of the stack and returns that element.<br>    ：rtype： int<br>    “””<br>    count = self.sq1.qsize()<br>    if count == 0：<br>        return False<br>    while count &gt; 1：<br>        x = self.sq1.get()<br>        self.sq1.put(x)<br>        count -= 1<br>    return self.sq1.get()  </p><p>def top(self)：<br>    “””<br>    Get the top element.<br>    ：rtype： int<br>    “””<br>    count = self.sq1.qsize()<br>    if count == 0：<br>        return False<br>    while count：<br>        x = self.sq1.get()<br>        self.sq1.put(x)<br>        count -= 1<br>    return x  </p><p>def empty(self)：<br>    “””<br>    Returns whether the stack is empty.<br>    ：rtype： bool<br>    “””<br>    return self.sq1.empty()  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>obj = MyStack2()<br>obj.push(1)<br>obj.push(3)<br>obj.push(4)<br>print(obj.pop())<br>print(obj.pop())<br>print(obj.pop())<br>print(obj.empty())  </p><h3 id="136-找出数据流的中位数"><a href="#136-找出数据流的中位数" class="headerlink" title="136. 找出数据流的中位数"></a>136. 找出数据流的中位数</h3><p>答：对于一个升序排序的数组，中位数为左半部分的最大值，右半部分的最小值，而左右两部分可以是无需的，只要保证左半部分的数均小于右半部分即可。因此，左右两半部分分别可用最大堆、最小堆实现。  </p><p>如果有奇数个数，则中位数放在左半部分；如果有偶数个数，则取左半部分的最大值、右边部分的最小值之平均值。  </p><p>分两种情况讨论： 当目前有偶数个数字时，数字先插入最小堆，然后选择最小堆的最小值插入最大堆（第一个数字插入左半部分的最小堆）。  </p><p>当目前有奇数个数字时，数字先插入最大堆，然后选择最大堆的最大值插入最小堆。 最大堆：根结点的键值是所有堆结点键值中最大者，且每个结点的值都比其孩子的值大。 最小堆：根结点的键值是所有堆结点键值中最小者，且每个结点的值都比其孩子的值小。  </p><h1 id="coding：utf-8-1"><a href="#coding：utf-8-1" class="headerlink" title="-- coding：utf-8 --"></a>-<em>- coding：utf-8 -</em>-</h1><p>from heapq import *  </p><p>class Solution：<br>def <strong>init</strong>(self)：<br>    self.maxheap = []<br>    self.minheap = []  </p><p>def Insert(self, num)：<br>    if (len(self.maxheap) + len(self.minheap)) &amp; 0x1：  # 总数为奇数插入最大堆<br>        if len(self.minheap) &gt; 0：<br>            if num &gt; self.minheap[0]：  # 大于最小堆里的元素<br>                heappush(self.minheap, num)  # 新数据插入最小堆<br>                heappush(self.maxheap, -self.minheap[0])  # 最小堆中的最小插入最大堆<br>                heappop(self.minheap)<br>            else：<br>                heappush(self.maxheap, -num)<br>        else：<br>            heappush(self.maxheap, -num)<br>    else：  # 总数为偶数 插入最小堆<br>        if len(self.maxheap) &gt; 0：  # 小于最大堆里的元素<br>            if num &lt; -self.maxheap[0]：<br>                heappush(self.maxheap, -num)  # 新数据插入最大堆<br>                heappush(self.minheap, -self.maxheap[0])  # 最大堆中的最大元素插入最小堆<br>                heappop(self.maxheap)<br>            else：<br>                heappush(self.minheap, num)<br>        else：<br>            heappush(self.minheap, num)  </p><p>def GetMedian(self, n=None)：<br>    if (len(self.maxheap) + len(self.minheap)) &amp; 0x1：<br>        mid = self.minheap[0]<br>    else：<br>        mid = (self.minheap[0] - self.maxheap[0]) / 2.0<br>    return mid  </p><p>if <strong>name</strong> == ‘<strong>main</strong>‘：<br>s = Solution()<br>s.Insert(1)<br>s.Insert(2)<br>s.Insert(3)<br>s.Insert(4)<br>print(s.GetMedian())  </p><h3 id="137-二叉搜索树中第-K-小的元素"><a href="#137-二叉搜索树中第-K-小的元素" class="headerlink" title="137. 二叉搜索树中第 K 小的元素"></a>137. 二叉搜索树中第 K 小的元素</h3><p>答： ??二叉搜索树(Binary Search Tree)，又名二叉排序树(Binary Sort Tree)。 ? 二叉搜索树是具有有以下性质的二叉树：?  </p><p>若左子树不为空，则左子树上所有节点的值均小于或等于它的根节点的值。<br>若右子树不为空，则右子树上所有节点的值均大于或等于它的根节点的值。<br>左、右子树也分别为二叉搜索树。  </p><p>二叉搜索树按照中序遍历的顺序打印出来正好就是排序好的顺序。所以对其遍历一个节点就进行计数，计数达到 k 的时候就结束。  </p><p>class TreeNode：<br>def <strong>init</strong>(self, x)：<br>    self.val = x<br>    self.left = None<br>    self.right = None  </p><p>class Solution：<br>count = 0<br>nodeVal = 0  </p><p>def kthSmallest(self, root, k)：<br>    “””<br>    ：type root： TreeNode<br>    ：type k： int<br>    ：rtype： int<br>    “””<br>    self.dfs(root, k)<br>    return self.nodeVal  </p><p>def dfs(self, node, k)：<br>    if node != None：<br>        self.dfs(node.left, k)<br>        self.count = self.count + 1<br>        if self.count == k：<br>            self.nodeVal = node.val<br>            # 将该节点的左右子树置为 None,来结束递归，减少时间复杂度<br>            node.left = None<br>            node.right = None<br>        self.dfs(node.right, k)  </p><p>爬虫相关  </p><h3 id="138-在-requests-模块中，requests-content-和-requests-text-什么区别"><a href="#138-在-requests-模块中，requests-content-和-requests-text-什么区别" class="headerlink" title="138. 在 requests 模块中，requests.content 和 requests.text 什么区别"></a>138. 在 requests 模块中，requests.content 和 requests.text 什么区别</h3><p>答： requests.content 获取的是字节，requests.text 获取的是文本内容。  </p><h3 id="139-简要写一下-lxml-模块的使用方法框架"><a href="#139-简要写一下-lxml-模块的使用方法框架" class="headerlink" title="139. 简要写一下 lxml 模块的使用方法框架"></a>139. 简要写一下 lxml 模块的使用方法框架</h3><p>答：  </p><p>from lxml import html<br>source=’’’  </p><div class="nam"><span>中国</span></div>  root=html.fromstring(source)  _content=root.xpath("string(//div[@class='nam'])")    if _content and isinstance(_content,list)：  content=_content[0]   elif isinstance(_content,str)：  content=_content      print(content)    ### 140. 说一说 scrapy 的工作流程    答：    首先还是先看张图    enter image description here    已 www.baidu.com 为例： 首先需要知道的事各个模块之间调用都是通过引擎进行的。    spider 把百度需要下载的第一个 url：www.baidu.com 交给引擎。  引擎把 url 交给调度器排序入队处理。  调度器把处理好的 request 返回给引擎。  通过引擎调动下载器，按照下载中间件的设置下载这个 request。  下载器下载完毕结果返回给引擎（如果失败：不好意思，这个 request 下载失败，然后引擎告诉调度器，这个 request 下载失败了，你记录一下，我们待会儿再下载。）  引擎调度 spider，把按照 Spider 中间件处理过了的请求，交给 spider 处理。  spider 把处理好的 url 和 item 传给引擎。  引擎根据不同的类型调度不同的模块，调度 Item Pipeline 处理 item。  把 url 交给调度器。 然后从第 4 步开始循环，直到获取到你需要的信息，    注意！只有当调度器中不存在任何 request 了，整个程序才会停止。  ### 141. scrapy 的去重原理    答：scrapy 本身自带一个去重中间件，scrapy 源码中可以找到一个 dupefilters.py 去重器。里面有个方法叫做 request_seen，它在 scheduler(发起请求的第一时间)的时候被调用。它代码里面调用了 request_fingerprint 方法（就是给 request 生成一个指纹）。    就是给每一个传递过来的 url 生成一个固定长度的唯一的哈希值。但是这种量级千万到亿的级别内存是可以应付的。  ### 142. scrapy 中间件有几种类，你用过哪些中间件    答： scrapy 的中间件理论上有三种(Schduler Middleware,Spider Middleware,Downloader Middleware)。在应用上一般有以下两种    爬虫中间件 Spider Middleware：主要功能是在爬虫运行过程中进行一些处理。  下载器中间件 Downloader Middleware：这个中间件可以实现修改 User-Agent 等 headers 信息，处理重定向，设置代理，失败重试，设置 cookies 等功能。    ### 143. 你写爬虫的时候都遇到过什么？反爬虫措施，你是怎么解决的？    答：    Headers： 从用户的 headers 进行反爬是最常见的反爬虫策略。Headers 是一种区分浏览器行为和机器行为中最简单的方法，还有一些网站会对 Referer （上级链接）进行检测（机器行为不太可能通过链接跳转实现）从而实现爬虫。 相应的解决措施：通过审查元素或者开发者工具获取相应的 headers 然后把相应的 headers 传输给 Python 的 requests，这样就能很好地绕过。    IP 限制 一些网站会根据你的 IP 地址访问的频率，次数进行反爬。也就是说如果你用单一的 IP 地址访问频率过高，那么服务器会在短时间内禁止这个 IP 访问。    解决措施：构造自己的 IP 代理池，然后每次访问时随机选择代理（但一些 IP 地址不是非常稳定，需要经常检查更新）。    UA 限制 UA 是用户访问网站时候的浏览器标识，其反爬机制与 ip 限制类似。    解决措施：使用随机 UA    验证码反爬虫或者模拟登陆 验证码：这个办法也是相当古老并且相当的有效果，如果一个爬虫要解释一个验证码中的内容，这在以前通过简单的图像识别是可以完成的，但是就现在来讲，验证码的干扰线，噪点都很多，甚至还出现了人类都难以认识的验证码。    相应的解决措施：验证码识别的基本方法：截图，二值化、中值滤波去噪、分割、紧缩重排（让高矮统一）、字库特征匹配识别。（Python 的 PIL 库或者其他），复杂的情况需求接入打码平台。    Ajax 动态加载 网页的不希望被爬虫拿到的数据使用 Ajax 动态加载，这样就为爬虫造成了绝大的麻烦，如果一个爬虫不具备 js 引擎，或者具备 js 引擎，但是没有处理 js 返回的方案，或者是具备了 js 引擎，但是没办法让站点显示启用脚本设置。基于这些情况，ajax 动态加载反制爬虫还是相当有效的。    Ajax 动态加载的工作原理是：从网页的 url 加载网页的源代码之后，会在浏览器里执行 JavaScript 程序。这些程序会加载出更多的内容，并把这些内容传输到网页中。这就是为什么有些网页直接爬它的 URL 时却没有数据的原因。    处理方法：找对应的 ajax 接口，一般数据返回类型为 json。    cookie 限制 一次打开网页会生成一个随机 cookie，如果再次打开网页这个 cookie 不存在，那么再次设置，第三次打开仍然不存在，这就非常有可能是爬虫在工作了。    解决措施：在 headers 挂上相应的 cookie 或者根据其方法进行构造（例如从中选取几个字母进行构造）。如果过于复杂，可以考虑使用 selenium 模块（可以完全模拟浏览器行为）。  ### 144. 为什么会用到代理？    答：如果使用同一个 ip 去不断的访问的网站的话,会很容易被封 ip，严重的永久封禁，导致当前的访问不了该网站。不只是通过程序，通过浏览器也无法访问。  ### 145. 代理失效了怎么处理？    答：一般通过大家代理池来实现代理切换等操作，来实现时时使用新的代理 ip，来避免代理失效的问题。  ### 146. 列出你知道 header 的内容以及信息    答： User-Agent：User-Agent 的内容包含发出请求的用户信息。 Accept：指定客户端能够接收的内容类型。 Accept-Encoding：指定浏览器可以支持的 web 服务器返回内容压缩编码类型。 Accept-Language：浏览器可接受的语言。 Connection：表示是否需要持久连接。（HTTP 1.1 默认进行持久连接）。 Content-Length：请求的内容长度。 If-Modified-Since：如果请求的部分在指定时间之后被修改则请求成功，未被修改则返回 304 代码。 Referer：先前网页的地址，当前请求网页紧随其后，即来路。  ### 147. 说一说打开浏览器访问 www.baidu.com 获取到结果，整个流程。    答： 浏览器向 DNS 服务器发送 baidu.com 域名解析请求。 DNS 服务器返回解析后的 ip 给客户端浏览器，浏览器想该 ip 发送页面请求。 DNS 服务器接收到请求后，查询该页面，并将页面发送给客户端浏览器。 客户端浏览器接收到页面后，解析页面中的引用，并再次向服务器发送引用资源请求。 服务器接收到资源请求后，查找并返回资源给客户端。 客户端浏览器接收到资源后，渲染，输出页面展现给用户。  ### 148. 爬取速度过快出现了验证码怎么处理    答：一般在爬取过程中出现了验证码根据不同的情况，处理不一样。 如果在一开始访问就有验证码,那么就想办法绕开验证码,比如通过 wap 端或者 app 去发现其他接口等，如果不行就得破解验证码了，复杂验证码就需要接入第三方打码平台了。 如果开始的时候没有验证码，爬了一段时间才出现验证码，这个情况就要考虑更换代理 ip 了。 可能因为同一个访问频率高导致的。  ### 149. scrapy 和 scrapy-redis 有什么区别？为什么选择 redis 数据库？    答： scrapy 是一个 Python 爬虫框架，爬取效率极高，具有高度定制性，但是不支持分布式。而 scrapy-redis 一套基于 redis 数据库、运行在 scrapy 框架之上的组件，可以让 scrapy 支持分布式策略，Slaver 端共享 Master 端 redis 数据库里的 item 队列、请求队列和请求指纹集合。    为什么选择 redis 数据库，因为 redis 支持主从同步，而且数据都是缓存在内存中的，所以基于 redis 的分布式爬虫，对请求和数据的高频读取效率非常高。  ### 150. 分布式爬虫主要解决什么问题    答：使用分布式主要目的就是为了给爬虫加速。解决了单个 ip 的限制，宽带的影响，以及 CPU 的使用情况和 io 等一系列操作  ### 151. 写爬虫是用多进程好？还是多线程好？ 为什么？    答： 多线程，因为爬虫是对网络操作属于 io 密集型操作适合使用多线程或者协程。  ### 152. 解析网页的解析器使用最多的是哪几个    答：lxml，pyquery  ### 153. 需要登录的网页，如何解决同时限制 ip，cookie,session（其中有一些是动态生成的）在不使用动态爬取的情况下？    答： 解决限制 IP 可以搭建代理 IP 地址池、adsl 拨号使用等。    不适用动态爬取的情况下可以使用反编译 JS 文件获取相应的文件，或者换用其他平台（比如手机端）看看是否可以获取相应的 json 文件，一般要学会习惯性的先找需要爬取网站的 h5 端页面，看看有没有提供接口，进而简化操作。  ### 154. 验证码的解决?    答： 图形验证码：干扰、杂色不是特别多的图片可以使用开源库 Tesseract 进行识别，太过复杂的需要借助第三方打码平台。 点击和拖动滑块验证码可以借助 selenium、无图形界面浏览器（chromedirver 或者 phantomjs）和 pillow 包来模拟人的点击和滑动操作，pillow 可以根据色差识别需要滑动的位置。  ### 155. 使用最多的数据库（mysql，mongodb，redis 等），对他的理解？    答： MySQL 数据库：开源免费的关系型数据库，需要实现创建数据库、数据表和表的字段，表与表之间可以进行关联（一对多、多对多），是持久化存储。    mongodb 数据库：是非关系型数据库，数据库的三元素是，数据库、集合、文档，可以进行持久化存储，也可作为内存数据库，存储数据不需要事先设定格式，数据以键值对的形式存储。    redis 数据库：非关系型数据库，使用前可以不用设置格式，以键值对的方式保存，文件格式相对自由，主要用与缓存数据库，也可以进行持久化存储。  网络编程  ### 156. TCP 和 UDP 的区别？    答： UDP 是面向无连接的通讯协议，UDP 数据包括目的端口号和源端口号信息。    优点：UDP 速度快、操作简单、要求系统资源较少，由于通讯不需要连接，可以实现广播发送。    缺点：UDP 传送数据前并不与对方建立连接，对接收到的数据也不发送确认信号，发送端不知道数据是否会正确接收，也不重复发送，不可靠。    TCP 是面向连接的通讯协议，通过三次握手建立连接，通讯完成时四次挥手。    优点：TCP 在数据传递时，有确认、窗口、重传、阻塞等控制机制，能保证数据正确性，较为可靠。    缺点：TCP 相对于 UDP 速度慢一点，要求系统资源较多。  ### 157. 简要介绍三次握手和四次挥手    答： 三次握手 第一次握手：主机 A 发送同步报文段（SYN）请求建立连接。 第二次握手：主机 B 听到连接请求，就将该连接放入内核等待队列当中，并向主机 A 发送针对 SYN 的确认 ACK，同时主机 B 也发送自己的请求建立连接（SYN）。 第三次握手：主机 A 针对主机 BSYN 的确认应答 ACK。    四次挥手 第一次挥手：当主机 A 发送数据完毕后，发送 FIN 结束报文段。 第二次挥手：主机 B 收到 FIN 报文段后，向主机 A 发送一个确认序号 ACK（为了防止在这段时间内，对方重传 FIN 报文段）。 第三次挥手：主机 B 准备关闭连接，向主机 A 发送一个 FIN 结束报文段。 第四次挥手：主机 A 收到 FIN 结束报文段后，进入 TIME_WAIT 状态。并向主机 B 发送一个 ACK 表示连接彻底释放。    除此之外经常看的问题还有，为什么 2、3 次挥手不能合在一次挥手中？ 那是因为此时 A 虽然不再发送数据了，但是还可以接收数据，B 可能还有数据要发送给 A，所以两次挥手不能合并为一次。  ### 158. 什么是粘包？ socket 中造成粘包的原因是什么？ 哪些情况会发生粘包现象？    答：TCP 是流式协议，只有字节流，流是没有边界的，根部就不存在粘包一说，一般粘包都是业务上没处理好造成的。    但是在描述这个现象的时候，可能还得说粘包。TCP 粘包通俗来讲，就是发送方发送的多个数据包，到接收方后粘连在一起，导致数据包不能完整的体现发送的数据。    导致 TCP 粘包的原因，可能是发送方的原因，也有可能是接受方的原因。    发送方 由于 TCP 需要尽可能高效和可靠，所以 TCP 协议默认采用 Nagle 算法，以合并相连的小数据包，再一次性发送，以达到提升网络传输效率的目的。但是接收方并不知晓发送方合并数据包，而且数据包的合并在 TCP 协议中是没有分界线的，所以这就会导致接收方不能还原其本来的数据包。    接收方 TCP 是基于“流”的。网络传输数据的速度可能会快过接收方处理数据的速度，这时候就会导致，接收方在读取缓冲区时，缓冲区存在多个数据包。在 TCP 协议中接收方是一次读取缓冲区中的所有内容，所以不能反映原本的数据信息。    一般的解决方案大概下面几种：    发送定长包。如果每个消息的大小都是一样的，那么在接收对等方只要累计接收数据，直到数据等于一个定长的数值就将它作为一个消息。  包尾加上\r\n 标记。FTP 协议正是这么做的。但问题在于如果数据正文中也含有\r\n，则会误判为消息的边界。  包头加上包体长度。包头是定长的 4 个字节，说明了包体的长度。接收对等方先接收包体长度，依据包体长度来接收包体。    并发  ### 159. 举例说明 concurrent.future 的中线程池的用法    答：    from concurrent.futures import ThreadPoolExecutor  import requests  URLS = ['http：//www.163.com', 'https：//www.baidu.com/', 'https：//github.com/']  def load_url(url)：      req= requests.get(url, timeout=60)      print(f'{url} page is {len(req.content))} bytes')  with ThreadPoolExecutor(max_workers=3) as pool：      pool.map(load_url,URLS)  print('主线程结束')    ### 160. 说一说多线程，多进程和协程的区别。    答： 概念：    进程：    进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,  进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间，  不同进程通过进程间通信来通信。由于进程比较重量，占据独立的内存，  所以上下文进程间的切换开销（栈、寄存器、虚拟内存、文件句柄等）比较大，但相对比较稳定安全。    线程：    线程是进程的一个实体,是 CPU 调度和分派的基本单位,  它是比进程更小的能独立运行的基本单位.  线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),  但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。  线程间通信主要通过共享内存，上下文切换很快，资源开销较少，但相比进程不够稳定容易丢失数据。    协程：    协程是一种用户态的轻量级线程，协程的调度完全由用户控制。  协程拥有自己的寄存器上下文和栈。  协程调度切换时，将寄存器上下文和栈保存到其他地方，在切回来的时候，恢复先前保存的寄存器上下文和栈，  直接操作栈则基本没有内核切换的开销，可以不加锁的访问全局变量，所以上下文的切换非常快。    区别： 进程与线程比较： 线程是指进程内的一个执行单元,也是进程内的可调度实体。线程与进程的区别：    1) 地址空间：线程是进程内的一个执行单元，进程内至少有一个线程，它们共享进程的地址空间，  而进程有自己独立的地址空间  2) 资源拥有：进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源  3) 线程是处理器调度的基本单位,但进程不是  4) 二者均可并发执行  5) 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口，  但是线程不能够独立执行，必须依存在应用程序中，由应用程序提供多个线程执行控制    协程与线程进行比较：    1) 一个线程可以多个协程，一个进程也可以单独拥有多个协程，这样 Python 中则能使用多核 CPU。  2) 线程进程都是同步机制，而协程则是异步  3) 协程能保留上一次调用时的状态，每次过程重入时，就相当于进入上一次调用的状态    ### 161. 简述 GIL    答： GIL：全局解释器锁。每个线程在执行的过程都需要先获取 GIL，保证同一时刻只有一个线程可以执行代码。    线程释放 GIL 锁的情况：在 IO 操作等可能会引起阻塞的 systemcall 之前,可以暂时释放 GIL，但在执行完毕后, 必须重新获取 GIL，Python3.x 使用计时器（执行时间达到阈值后，当前线程释放 GIL）或 Python2.x，tickets 计数达到 100 。    Python 使用多进程是可以利用多核的 CPU 资源的。    多线程爬取比单线程性能有提升，因为遇到 IO 阻塞会自动释放 GIL 锁。  ### 162. 进程之间如何通信    答： 可以通过队列的形式，示例如下    from multiprocessing import Queue, Process  import time, random    # 要写入的数据  list1 = ["java", "Python", "JavaScript"]      def write(queue)：  """  向队列中添加数据  ：param queue：  ：return：  """  for value in list1：      print(f"正在向队列中添加数据-->{value}")      # put_nowait 不会等待队列有空闲位置再放入数据，如果数据放入不成功就直接崩溃,比如数据满了。put 的话就会一直等待      queue.put_nowait(value)      time.sleep(random.random())      def read(queue)：    while True：      # 判断队列是否为空      if not queue.empty()：          # get_nowait 队列为空，取值的时候不等待，但是取不到值那么直接崩溃了          value = queue.get_nowait()          print(f'从队列中取到的数据为-->{value}')          time.sleep(random.random())      else：          break    if __name__ == '__main__'：  # 父进程创建出队列，通过参数的形式传递给子进程  #queue = Queue(2)  queue = Queue()    # 创建两个进程 一个写数据 一个读数据  write_data = Process(target=write, args=(queue,))  read_data = Process(target=read, args=(queue,))    # 启动进程 写入数据  write_data.start()  # 使用 join 等待写数据结束  write_data.join()  # 启动进程  读取数据  print('*' * 20)  read_data.start()  # 使用 join  等待读数据结束  read_data.join()    print('所有的数据都写入并读取完成。。。')    ### 163. IO 多路复用的作用？    答： 阻塞 I/O 只能阻塞一个 I/O 操作，而 I/O 复用模型能够阻塞多个 I/O 操作，所以才叫做多路复用。    I/O 多路复用是用于提升效率，单个进程可以同时监听多个网络连接 IO。 在 IO 密集型的系统中， 相对于线程切换的开销问题，IO 多路复用可以极大的提升系统效率。  ### 164. select、poll、epoll 模型的区别？    答： select，poll，epoll 都是 IO 多路复用的机制。I/O 多路复用就通过一种机制，可以监视多个描述符，一旦某个描述符就绪（一般是读就绪或者写就绪），能够通知程序进行相应的读写操作。    select 模型： select 目前几乎在所有的平台上支持，其良好跨平台支持也是它的一个优点。select 的一 个缺点在于单个进程能够监视的文件描述符的数量存在最大限制，在 Linux 上一般为 1024，可以通过修改宏定义甚至重新编译内核的方式提升这一限制，但 是这样也会造成效率的降低。    poll 模型： poll 和 select 的实现非常类似，本质上的区别就是存放 fd 集合的数据结构不一样。select 在一个进程内可以维持最多 1024 个连接，poll 在此基础上做了加强，可以维持任意数量的连接。    但 select 和 poll 方式有一个很大的问题就是，我们不难看出来 select 是通过轮训的方式来查找是否可读或者可写，打个比方，如果同时有 100 万个连接都没有断开，而只有一个客户端发送了数据，所以这里它还是需要循环这么多次，造成资源浪费。所以后来出现了 epoll 系统调用。    epoll 模型： epoll 是 select 和 poll 的增强版，epoll 同 poll 一样，文件描述符数量无限制。但是也并不是所有情况下 epoll 都比 select/poll 好，比如在如下场景：在大多数客户端都很活跃的情况下，系统会把所有的回调函数都唤醒，所以会导致负载较高。既然要处理这么多的连接，那倒不如 select 遍历简单有效。  ### 165. 什么是并发和并行？    答：“并行是指同一时刻同时做多件事情，而并发是指同一时间间隔内做多件事情”。    并发与并行是两个既相似而又不相同的概念：并发性，又称共行性，是指能处理多个同时性活动的能力；并行是指同时发生的两个并发事件，具有并发的含义，而并发则不一定并行，也亦是说并发事件之间不一定要同一时刻发生。    并发的实质是一个物理 CPU(也可以多个物理 CPU) 在若干道程序之间多路复用，并发性是对有限物理资源强制行使多用户共享以提高效率。 并行性指两个或两个以上事件或活动在同一时刻发生。在多道程序环境下，并行性使多个程序同一时刻可在不同 CPU 上同时执行。    并行，是每个 CPU 运行一个程序。  ### 166. 一个线程 1 让线程 2 去调用一个函数怎么实现    答：    import threading      def func1(t2)：  print('正在执行函数func1')  t2.start()      def func2()：  print('正在执行函数func2')      if __name__ == '__main__'：  t2 = threading.Thread(target=func2)  t1 = threading.Thread(target=func1, args=(t2,))  t1.start()    ### 167. 解释什么是异步非阻塞？    答： 异步 异步与同步相对，当一个异步过程调用发出后，调用者在没有得到结果之前，就可以继续执行后续操作。当这个调用完成后，一般通过状态、通知和回调来通知调用者。对于异步调用，调用的返回并不受调用者控制。    非阻塞 非阻塞是这样定义的，当线程遇到 I/O 操作时，不会以阻塞的方式等待 I/O 操作的完成或数据的返回，而只是将 I/O 请求发送给操作系统，继续执行下一条语句。当操作系统完成 I/O 操作时，以事件的形式通知执行 I/O 操作的线程，线程会在特定时候处理这个事件。简答理解就是如果程序不会卡住，可以继续执行，就是说非阻塞的。  ### 168. threading.local 的作用？    答： threading.local()这个方法是用来保存一个全局变量，但是这个全局变量只有在当前线程才能访问，如果你在开发多线程应用的时候，需要每个线程保存一个单独的数据供当前线程操作，可以考虑使用这个方法，简单有效。代码示例    import threading  import time    a = threading.local()#全局对象    def worker()：  a.x = 0  for i in range(200)：      time.sleep(0.01)      a.x += 1  print(threading.current_thread(),a.x)    for i in range(20)：  threading.Thread(target=worker).start()    Git 面试题  ### 169. 说说你知道的 git 命令    答： git init：该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干 git clone url：将服务器代码下载到本地 git pull：将服务器的代码拉到本地进行同步，如果本地有修改会产生冲突。 git push：提交本地修改的代码到服务器 git checkout -b branch：创建并切换分支 git status：查看修改状态 git add 文件名：提交到暂存区 git commit -m "提交内容"：输入提交的注释内容 git log：查看提交的日志情况  ### 170. git 如何查看某次提交修改的内容    答：我们首先可以 git log 显示历史的提交列表 之后我们用 git show 便可以显示某次提交的修改内容 同样 git show filename 可以显示某次提交的某个内容的修改信息。  ]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python高级编程技巧</title>
      <link href="python/collection/advance-skills/"/>
      <url>python/collection/advance-skills/</url>
      
        <content type="html"><![CDATA[<h3 id="如何在列表-字典-集合中根据条件筛选数据"><a href="#如何在列表-字典-集合中根据条件筛选数据" class="headerlink" title="如何在列表,字典,集合中根据条件筛选数据"></a>如何在列表,字典,集合中根据条件筛选数据</h3><p>方法1:通过迭代来进行判断筛选</p><p>解决方案<br>函数式编程:</p><h3 id="如何统计序列中元素的出现频度"><a href="#如何统计序列中元素的出现频度" class="headerlink" title="如何统计序列中元素的出现频度"></a>如何统计序列中元素的出现频度</h3><p>解决方案:使用collections.Counter对象</p><p>将序列传入Counter的构造器,得到Counter对象是元素频度的字典<br>Counter.most_common(n)方法得到频度最高的n个元素的列表</p><h3 id="如何感觉字典中的值的大小-对字典中的项进行排序"><a href="#如何感觉字典中的值的大小-对字典中的项进行排序" class="headerlink" title="如何感觉字典中的值的大小,对字典中的项进行排序"></a>如何感觉字典中的值的大小,对字典中的项进行排序</h3><p>解决方案:使用内置函数sorted</p><ol><li>利用zip将字典数据转换成为元组</li><li>传递sorted哈数的key参数</li></ol><h3 id="如何快速找到多个字典中的多个公共键-key"><a href="#如何快速找到多个字典中的多个公共键-key" class="headerlink" title="如何快速找到多个字典中的多个公共键(key)?"></a>如何快速找到多个字典中的多个公共键(key)?</h3><p>利用集合(set)的交集操作<br>step1:使用字典的viewkeys()方法,得到一个字典keys的集合<br>step2:使用map函数,得到所有字典的keys的集合<br>step3:使用reduce函数,取得所有字典的keys的集合的交集</p><h3 id="如何让字典保持有序"><a href="#如何让字典保持有序" class="headerlink" title="如何让字典保持有序"></a>如何让字典保持有序</h3><p>使用collections.OrderedDict<br>以OrderedDict替代内置字典Dict,依次将选手的成绩存入OrderedDict</p><h3 id="如何实现历史记录功能"><a href="#如何实现历史记录功能" class="headerlink" title="如何实现历史记录功能"></a>如何实现历史记录功能</h3><p>使用容量为n的队列存储历史记录<br>使用标准库collections中的deque,它是以双端循环队列<br>程序退出前,可以使用pickle将队列对象存入文件,在此运行程序时将其导入</p><h3 id="如何实现可迭代对象和迭代器对象"><a href="#如何实现可迭代对象和迭代器对象" class="headerlink" title="如何实现可迭代对象和迭代器对象"></a>如何实现可迭代对象和迭代器对象</h3><p>有可迭代对象,得到迭代器</p><p>通过列表调用迭代器接口<br>通过字符串调用迭代器接口</p><h3 id="如何使用生成器函数实现可迭代对象"><a href="#如何使用生成器函数实现可迭代对象" class="headerlink" title="如何使用生成器函数实现可迭代对象"></a>如何使用生成器函数实现可迭代对象</h3><p>将该类的__iter__方法实现成生成器函数,每次yield返回一个素数</p><h3 id="如何读写csv数据"><a href="#如何读写csv数据" class="headerlink" title="如何读写csv数据"></a>如何读写csv数据</h3><p>使用python标准库中的csv模块,可以使用起哄reader和write完成csv文件的读写</p><h3 id="如何读写json数据"><a href="#如何读写json数据" class="headerlink" title="如何读写json数据"></a>如何读写json数据</h3><p>使用python标准库中的json模块,可以使用loads,dumps函数可以完成json数据的读写</p><h3 id="如何解析和构建xml文档"><a href="#如何解析和构建xml文档" class="headerlink" title="如何解析和构建xml文档"></a>如何解析和构建xml文档</h3><p>使用python标准库中的xml.etree.ElementTree,其中的parse函数可以解析xml文档</p><h3 id="如何读写Excel文件"><a href="#如何读写Excel文件" class="headerlink" title="如何读写Excel文件"></a>如何读写Excel文件</h3><p>使用第三方库xlrd,xlwt,这两个库分别用于Excel的读写</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(无头的浏览器)是什么鬼?</title>
      <link href="python/collection/python-headless-chrome/"/>
      <url>python/collection/python-headless-chrome/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.jianshu.com/p/11d519e2d0cb">https://www.jianshu.com/p/11d519e2d0cb</a></p><h1 class="_1RuRku">用Python驱动Headless Chrome</h1><article class="_2rhmJa">    <div class="image-package">        <div class="image-container" style="max-width: 650px; max-height: 453px; background-color: transparent;">            <div class="image-container-fill" style="padding-bottom: 69.69%;"></div>            <div class="image-view" data-width="650" data-height="453"><img                    data-original-src="//upload-images.jianshu.io/upload_images/618241-fbc4471c5a9bfcf2.png"                    data-original-width="650" data-original-height="453" data-original-format="image/png"                    data-original-filesize="163264" data-image-index="0" style="cursor: zoom-in;" class=""                    src="//upload-images.jianshu.io/upload_images/618241-fbc4471c5a9bfcf2.png?imageMogr2/auto-orient/strip|imageView2/2/w/650/format/webp">            </div>        </div>        <div class="image-caption">headless chrome.png</div>    </div>    <blockquote>        <p>Headless Browser(无头的浏览器)是什么鬼?</p>    </blockquote>    <p>简而言之，Headless Browser是没有图形用户界面(GUI)的web浏览器，通常是通过编程或命令行界面来控制的。</p>    <p>Headless Browser的许多用处之一是自动化可用性测试或测试浏览器交互。如果您正在尝试检查页面在不同的浏览器中呈现的方式，或者确认页面元素在用户启动某个工作流之后出现，那么使用Headless        Browser可以提供大量的帮助。除此之外，如果内容是动态呈现的(比如通过Javascript)，web抓取等传统的面向web的任务就很难做了。使用Headless        Browser可以方便地访问这些内容，因为内容的呈现方式与完全浏览器中的内容完全相同。</p>    <p>基于不同的浏览器，有不同的浏览器引擎。(<a            href="https://link.jianshu.com?t=http%3A%2F%2Fwww.cnblogs.com%2Fwangjunqiao%2Fp%2F5212561.html"            target="_blank" rel="nofollow">http://www.cnblogs.com/wangjunqiao/p/5212561.html</a>)</p>    <p><em>主流浏览器所使用的内核分类</em></p>    <p>Trident内核：IE,MaxThon,TT,The World,360,搜狗浏览器等<br>        Gecko内核：Netscape6及以上版本，FF,MozillaSuite/SeaMonkey等<br>        Presto内核：Opera7及以上<br>        Webkit内核：Safari,Chrome等</p>    <p>先让我们看看浏览器处理过程中的每一个步骤：</p>    <p>1.处理HTML脚本，生成DOM树<br>        2.处理CSS脚本，生成CSSOM树 （DOM和CSSOM是独立的数据结构）<br>        3.将DOM树和CSSOM树合并为渲染树<br>        4.对渲染树中的内容进行布局，计算每个节点的几何外观<br>        5.将渲染树中的每个节点绘制到屏幕中</p>    <p>Headless Browser实际就是节约了第4,5步的时间。</p>    <p>3年前，无头浏览器 PhantomJS 已经如火如荼出现了，紧跟着 NightmareJS        也成为一名巨星。无头浏览器带来巨大便利性：页面爬虫、自动化测试、WebAutomation...用过PhantomJS的都知道，它的环境是运行在一个封闭的沙盒里面，在环境内外完全不可通信，包括API、变量、全局方法调用等。</p>    <p><strong>Headless Chrome和Python</strong><br>        在发布Headless Chrome之前，当你需要自动化浏览器的时候随时都有可能涉及多个窗口或标签，你必须担心CPU和/或内存的使用。这两种方式都与必须从被请求的URL中显示显示的图形的浏览器相关联。</p>    <p>当使用一个无头的浏览器时，我们不用担心这个。因此，我们可以预期我们编写的脚本的内存开销会降低，执行速度也会更快。<br>        而Chrome从59版本开始 推出了 headless mode（当时仅支持Mac和Linux），而目前最新的Chrome63版已经开始在windows上支持headless mode。</p>    <p><strong>安装Headless Chrome 在windows</strong><br>        Selenium操作chrome浏览器需要有ChromeDriver驱动来协助。<br>        什么是ChromeDriver？</p>    <p>ChromeDriver是Chromium        team开发维护的，它是实现WebDriver有线协议的一个单独的服务。ChromeDriver通过chrome的自动代理框架控制浏览器，建议从以下地址直接下载最新的版本：<strong><a                href="https://link.jianshu.com?t=https%3A%2F%2Fchromedriver.storage.googleapis.com%2Findex.html%3Fpath%3D2.34%2F"                target="_blank" rel="nofollow">ChromeDriver 2.34</a></strong><br>        它才可以支持Chrome v61-63。<br>        可以将此driver放置于：C:\Program Files\Google\Chrome\Application\ （对应的Chrome安装目录下）</p>    <p><strong>安装Selenium 在windows</strong><br>        cmd命令里面运行：<br>        $pip install selenium</p>    <p><strong>编写对应的脚本</strong><br>        编写一个对应的百度搜索的脚本</p>    <div class="_2Uzcx_">        <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy"                                                                  class="anticon anticon-copy">            <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"                 fill="currentColor" aria-hidden="true">                <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>            </svg>        </i></button>        <pre class="line-numbers  language-python"><code class="  language-python"><span                class="token keyword">import</span> os<span class="token keyword">from</span> selenium <span class="token keyword">import</span> webdriver<span class="token keyword">from</span> selenium<span class="token punctuation">.</span>webdriver<span                    class="token punctuation">.</span>common<span class="token punctuation">.</span>keys <span                    class="token keyword">import</span> Keys<span class="token keyword">from</span> selenium<span class="token punctuation">.</span>webdriver<span                    class="token punctuation">.</span>chrome<span class="token punctuation">.</span>options <span                    class="token keyword">import</span> Options<span class="token keyword">import</span> time<p>chrome_options <span class="token operator">=</span> Options<span class="token punctuation">(</span><span                    class="token punctuation">)</span><br>chrome_options<span class="token punctuation">.</span>add_argument<span class="token punctuation">(</span><span                    class="token string">“–headless”</span><span class="token punctuation">)</span></p><p>base_url <span class="token operator">=</span> <span class="token string">“<a href="http://www.baidu.com/&quot;">http://www.baidu.com/&quot;</a></span><br><span class="token comment">#对应的chromedriver的放置目录</span><br>driver <span class="token operator">=</span> webdriver<span class="token punctuation">.</span>Chrome<span                    class="token punctuation">(</span>executable_path<span class="token operator">=</span><span                    class="token punctuation">(</span><span class="token string">r’C:\Program Files\Google\Chrome\Application\chromedriver.exe’</span><span                    class="token punctuation">)</span><span class="token punctuation">,</span> chrome_options<span                    class="token operator">=</span>chrome_options<span class="token punctuation">)</span></p><p>driver<span class="token punctuation">.</span>get<span class="token punctuation">(</span>base_url <span                    class="token operator">+</span> <span class="token string">“/“</span><span                    class="token punctuation">)</span></p><p>start_time<span class="token operator">=</span>time<span class="token punctuation">.</span>time<span                    class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">‘this is start_time ‘</span><span                    class="token punctuation">,</span>start_time<span class="token punctuation">)</span></p><p>driver<span class="token punctuation">.</span>find_element_by_id<span class="token punctuation">(</span><span                    class="token string">“kw”</span><span class="token punctuation">)</span><span                    class="token punctuation">.</span>send_keys<span class="token punctuation">(</span><span                    class="token string">“selenium webdriver”</span><span class="token punctuation">)</span><br>driver<span class="token punctuation">.</span>find_element_by_id<span class="token punctuation">(</span><span                    class="token string">“su”</span><span class="token punctuation">)</span><span                    class="token punctuation">.</span>click<span class="token punctuation">(</span><span                    class="token punctuation">)</span><br>driver<span class="token punctuation">.</span>save_screenshot<span class="token punctuation">(</span><span                    class="token string">‘screen.png’</span><span class="token punctuation">)</span></p><p>driver<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span                    class="token punctuation">)</span></p><p>end_time<span class="token operator">=</span>time<span class="token punctuation">.</span>time<span                    class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">‘this is end_time ‘</span><span                    class="token punctuation">,</span>end_time<span class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    </div><br>    <p>以上的脚本运行完成后，你会在你的当前目录看到一个类似于下面画面的screen.png.</p><br>    <br><br>    <div class="image-package"><br>        <div class="image-container" style="max-width: 700px; max-height: 600px; background-color: transparent;"><br>            <div class="image-container-fill" style="padding-bottom: 75.0%;"></div><br>            <div class="image-view" data-width="800" data-height="600"><img                    data-original-src="//upload-images.jianshu.io/upload_images/618241-e3d8deff450aa43c.png"                    data-original-width="800" data-original-height="600" data-original-format="image/png"                    data-original-filesize="73100" data-image-index="1" style="cursor: zoom-in;" class=""                    src="//upload-images.jianshu.io/upload_images/618241-e3d8deff450aa43c.png?imageMogr2/auto-orient/strip|imageView2/2/w/800/format/webp"><br>            </div><br>        </div><br>        <div class="image-caption">screen.png</div><br>    </div><br>    <p>可以看出上面的写法和直接使用Selenium调用Chrome浏览器的时候极其类似，只是多添加了对chrome_options的重写。</p><br>    <p>据运行的试验表明，Headelss 的确比Headed的浏览器在内存消耗，运行时间，CPU占用上面都有一定的优势。</p><br>    <div class="image-package"><br>        <div class="image-container" style="max-width: 700px; max-height: 118px; background-color: transparent;"><br>            <div class="image-container-fill" style="padding-bottom: 14.499999999999998%;"></div><br>            <div class="image-view" data-width="814" data-height="118"><img                    data-original-src="//upload-images.jianshu.io/upload_images/618241-1a0846f6b318549d.png"                    data-original-width="814" data-original-height="118" data-original-format="image/png"                    data-original-filesize="21138" data-image-index="2" style="cursor: zoom-in;" class=""                    src="//upload-images.jianshu.io/upload_images/618241-1a0846f6b318549d.png?imageMogr2/auto-orient/strip|imageView2/2/w/814/format/webp"><br>            </div><br>        </div><br>        <div class="image-caption">headless对比.png</div><br>    </div><br>    <p>使用Headless Chrome也许能让你的自动化测试运行更快，而且在视觉测试上面也有一定的优势。感兴趣的朋友可以上手试试。</p></p></article><div></div><div class="_1kCBjS">    <div class="_18vaTa">        <div class="_3BUZPB">            <div class="_2Bo4Th" role="button" tabindex="-1" aria-label="给文章点赞"><i aria-label="ic-like"                                                                                   class="anticon">                <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">                    <use xlink:href="#ic-like"></use>                </svg>            </i></div>            <span class="_1LOh_5" role="button" tabindex="-1" aria-label="查看点赞列表">16人点赞<i aria-label="icon: right"                                                                                          class="anticon anticon-right"><svg                    viewBox="64 64 896 896" focusable="false" class="" data-icon="right" width="1em" height="1em"                    fill="currentColor" aria-hidden="true"><path                    d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span>        </div>        <div class="_3BUZPB">            <div class="_2Bo4Th" role="button" tabindex="-1"><i aria-label="ic-dislike" class="anticon">                <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">                    <use xlink:href="#ic-dislike"></use>                </svg>            </i></div>        </div>    </div>    <div class="_18vaTa"><a class="_3BUZPB _1x1ok9 _1OhGeD" href="/nb/10356021" target="_blank"                            rel="noopener noreferrer"><i aria-label="ic-notebook" class="anticon">        <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">            <use xlink:href="#ic-notebook"></use>        </svg>    </i><span>周边工具</span></a>        <div class="_3BUZPB ant-dropdown-trigger">            <div class="_2Bo4Th"><i aria-label="ic-others" class="anticon">                <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">                    <use xlink:href="#ic-others"></use>                </svg>            </i></div>        </div>    </div></div><div class="_19DgIp" style="margin-top:24px;margin-bottom:24px"></div><div class="_13lIbp">    <div class="_191KSt">"想转载的，给杯茶钱呀~~"</div>    <button type="button" class="_1OyPqC _3Mi9q9 _2WY0RL _1YbC5u"><span>赞赏支持</span></button>    <span class="_3zdmIj">还没有人赞赏，支持一下</span></div><div class="d0hShY"><a class="_1OhGeD" href="/u/42c47cc2c681" target="_blank" rel="noopener noreferrer"><img        class="_27NmgV"        src="//upload.jianshu.io/users/upload_avatars/618241/5c425905-46fd-46ac-ba24-192d650f6d33.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/100/h/100/format/webp"        alt="  "></a>    <div class="Uz-vZq">        <div class="Cqpr1X"><a class="HC3FFO _1OhGeD" href="/u/42c47cc2c681" title="CC先生之简书" target="_blank"                               rel="noopener noreferrer">CC先生之简书</a><span class="_2WEj6j" title="04年入IT坑的老中医/为学日益 为道日损，损之又损，以至于无为/一切皆测试">04年入IT坑的老中医/为学日益 为道日损，损之又损，以至于无为/一切皆测试</span></div>        <div class="lJvI3S">            <span>总资产360 (约33.59元)</span><span>共写了21.3W字</span><span>获得694个赞</span><span>共684个粉丝</span></div>    </div>    <button data-locale="zh-CN" type="button" class="_1OyPqC _3Mi9q9"><span>关注</span></button></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于C10K问题详解</title>
      <link href="python/tornado/c10k/"/>
      <url>python/tornado/c10k/</url>
      
        <content type="html"><![CDATA[<p>本文转自:<a href="https://www.jianshu.com/p/ba7fa25d3590">https://www.jianshu.com/p/ba7fa25d3590</a></p><h3>C10K问题由来</h3><p>    随着互联网的普及，应用的用户群体几何倍增长，此时服务器性能问题就出现。最初的服务器是基于进程/线程模型。新到来一个TCP连接，就需要分配一个进程。假如有C10K，就需要创建1W个进程，可想而知单机是无法承受的。那么如何突破单机性能是高性能网络编程必须要面对的问题，进而这些局限和问题就统称为C10K问题，最早是由Dan    Kegel进行归纳和总结的，并且他也系统的分析和提出解决方案。</p><h3>C10K问题的本质</h3><p>C10K问题的本质上是操作系统的问题。对于Web 1.0/2.0时代的操作系统，传统的同步阻塞I/O模型处理方式都是requests per    second。当创建的进程或线程多了，数据拷贝频繁（缓存I/O、内核将数据拷贝到用户进程空间、阻塞，进程/线程上下文切换消耗大， 导致操作系统崩溃，这就是C10K问题的本质。</p><p>可见, 解决C10K问题的关键就是尽可能减少这些CPU资源消耗。</p><h3>C10K问题的解决方案</h3><p>从网络编程技术的角度来说，主要思路：</p><ol>    <li>每个连接分配一个独立的线程/进程</li>    <li>同一个线程/进程同时处理多个连接</li></ol><h4>每个进程/线程处理一个连接</h4><p>该思路最为直接，但是申请进程/线程是需要系统资源的，且系统需要管理这些进程/线程，所以会使资源占用过多，可扩展性差</p><h4>每个进程/线程同时处理 多个连接(I/O多路复用)</h4><ol>    <li>        select方式：使用fd_set结构体告诉内核同时监控那些文件句柄，使用逐个排查方式去检查是否有文件句柄就绪或者超时。该方式有以下缺点：文件句柄数量是有上线的，逐个检查吞吐量低，每次调用都要重复初始化fd_set。    </li>    <li>poll方式：该方式主要解决了select方式的2个缺点，文件句柄上限问题(链表方式存储)以及重复初始化问题(不同字段标注关注事件和发生事件)，但是逐个去检查文件句柄是否就绪的问题仍然没有解决。</li>    <li>        epoll方式：该方式可以说是C10K问题的killer，他不去轮询监听所有文件句柄是否已经就绪。epoll只对发生变化的文件句柄感兴趣。其工作机制是，使用"事件"的就绪通知方式，通过epoll_ctl注册文件描述符fd，一旦该fd就绪，内核就会采用类似callback的回调机制来激活该fd,        epoll_wait便可以收到通知, 并通知应用程序。而且epoll使用一个文件描述符管理多个描述符,将用户进程的文件描述符的事件存放到内核的一个事件表中,        这样数据只需要从内核缓存空间拷贝一次到用户进程地址空间。而且epoll是通过内核与用户空间共享内存方式来实现事件就绪消息传递的，其效率非常高。但是epoll是依赖系统的(Linux)。    </li>    <li>异步I/O以及Windows，该方式在windows上支持很好，这里就不具体介绍啦。</li></ol><p>参考：</p><ol>    <li><a href="https://link.jianshu.com?t=http%3A%2F%2Fwww.ideawu.net%2Fblog%2Farchives%2F740.html"           target="_blank" rel="nofollow">构建C1000K的服务器(1) – 基础</a></li>    <li><a href="https://link.jianshu.com?t=http%3A%2F%2Fwww.52im.net%2Fthread-566-1-1.html" target="_blank"           rel="nofollow">高性能网络编程(二)：上一个10年，著名的C10K并发连接问题</a></li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于curl的使用详解</title>
      <link href="python/tornado/curl/"/>
      <url>python/tornado/curl/</url>
      
        <content type="html"><![CDATA[<p>本文转自:<a href="https://www.jianshu.com/p/f05bbd5007d9">https://www.jianshu.com/p/f05bbd5007d9</a></p><div class="image-package">    <div class="image-container" style="max-width: 441px; max-height: 97px; background-color: transparent;">        <div class="image-container-fill" style="padding-bottom: 22.0%;"></div>        <div class="image-view" data-width="441" data-height="97"><img                data-original-src="//upload-images.jianshu.io/upload_images/2733312-11e482557148c9b5.png"                data-original-width="441" data-original-height="97" data-original-format="image/png"                data-original-filesize="12765" data-image-index="0" style="cursor: zoom-in;" class=""                src="//upload-images.jianshu.io/upload_images/2733312-11e482557148c9b5.png?imageMogr2/auto-orient/strip|imageView2/2/w/441/format/webp">        </div>    </div>    <div class="image-caption"></div></div><p>curl 是一种命令行工具，作用是发出网络请求，然后获取数据，显示在"标准输出"（stdout）上面。它支持多种协议，下面列举其常用功能。</p><h5>一、查看网页源码</h5><p>直接在 curl 命令后加上网址，就可以看到网页源码。以网址 <a href="https://link.jianshu.com?t=http://www.sina.com" target="_blank"                                     rel="nofollow">www.sina.com</a>为例（选择该网址，主要因为它的网页代码较短）。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-xml"><code class="  language-xml">$ curl www.sina.com<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span        class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span        class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>301 Moved Permanently<span                class="token tag"><span class="token tag"><span                class="token punctuation">&lt;/</span>title</span><span                class="token punctuation">&gt;</span></span><span                class="token tag"><span class="token tag"><span                class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span> <span        class="token attr-name">bgcolor</span><span class="token attr-value"><span        class="token punctuation">=</span><span class="token punctuation">"</span>white<span        class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>center</span><span        class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;</span>h1</span><span class="token punctuation">&gt;</span></span>301 Moved Permanently<span                class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span                class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;/</span>center</span><span                class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>hr</span><span        class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;</span>center</span><span class="token punctuation">&gt;</span></span>nginx<span                class="token tag"><span class="token tag"><span                class="token punctuation">&lt;/</span>center</span><span                class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span        class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span        class="token punctuation">&gt;</span></span><p><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>如果要把这个网页保存下来，可以使用 <code>-o</code> 参数：</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">$ curl <span            class="token operator">-</span>o <span class="token punctuation">[</span>文件名<span            class="token punctuation">]</span> www<span class="token punctuation">.</span>sina<span            class="token punctuation">.</span>com<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><h5>二、自动跳转</h5><p>有的网址是自动跳转的。使用 <code>-L</code> 参数，curl 就会跳转到新的网址。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">$ curl <span            class="token operator">-</span><span class="token constant">L</span> www<span            class="token punctuation">.</span>sina<span            class="token punctuation">.</span>com<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>键入上面的命令，结果自动跳转为 <a href="https://link.jianshu.com?t=http://www.sina.com.cn" target="_blank" rel="nofollow">www.sina.com.cn</a>。</p><h5>三、显示头信息</h5><p><code>-i</code> 参数可以显示 http response 的头信息，连同网页代码一起。<code>-I</code> 参数则只显示 http response 的头信息。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-jsx"><code class="  language-jsx">$ curl <span            class="token operator">-</span>i www<span class="token punctuation">.</span>sina<span            class="token punctuation">.</span>com<span class="token constant">HTTP</span><span class="token operator">/</span><span class="token number">1.1</span> <span                class="token number">301</span> Moved PermanentlyServer<span class="token punctuation">:</span> nginxDate<span class="token punctuation">:</span> Tue<span class="token punctuation">,</span> <span                class="token number">23</span> Aug <span class="token number">2016</span> <span                class="token number">08</span><span class="token punctuation">:</span><span                class="token number">30</span><span class="token punctuation">:</span><span                class="token number">16</span> <span class="token constant">GMT</span>Content<span class="token operator">-</span>Type<span class="token punctuation">:</span> text<span                class="token operator">/</span>htmlLocation<span class="token punctuation">:</span> http<span class="token punctuation">:</span><span                class="token operator">/</span><span class="token regex">/www.sina.com.cn/</span>Expires<span class="token punctuation">:</span> Tue<span class="token punctuation">,</span> <span class="token number">23</span> Aug <span                class="token number">2016</span> <span class="token number">08</span><span                class="token punctuation">:</span><span class="token number">32</span><span                class="token punctuation">:</span><span class="token number">16</span> <span                class="token constant">GMT</span>Cache<span class="token operator">-</span>Control<span class="token punctuation">:</span> max<span                class="token operator">-</span>age<span class="token operator">=</span><span                class="token number">120</span>Age<span class="token punctuation">:</span> <span class="token number">102</span>Content<span class="token operator">-</span>Length<span class="token punctuation">:</span> <span class="token number">178</span><span class="token constant">X</span><span class="token operator">-</span>Cache<span class="token punctuation">:</span> <span                class="token constant">HIT</span> <span class="token keyword">from</span> xd33<span                class="token operator">-</span><span class="token number">83.</span>sina<span                class="token punctuation">.</span>com<span class="token punctuation">.</span>cn<p><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span        class="token punctuation">&gt;</span></span><span class="token plain-text"><br></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span                class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;</span>title</span><span                class="token punctuation">&gt;</span></span><span                class="token plain-text">301 Moved Permanently</span><span class="token tag"><span                class="token tag"><span class="token punctuation">&lt;/</span>title</span><span                class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;/</span>head</span><span                class="token punctuation">&gt;</span></span><span class="token plain-text"><br></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span> <span                class="token attr-name">bgcolor</span><span class="token attr-value"><span                class="token punctuation">=</span><span class="token punctuation">“</span>white<span                class="token punctuation">“</span></span><span class="token punctuation">&gt;</span></span><span                class="token plain-text"><br></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>center</span><span                class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;</span>h1</span><span                class="token punctuation">&gt;</span></span><span                class="token plain-text">301 Moved Permanently</span><span class="token tag"><span                class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span                class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;/</span>center</span><span                class="token punctuation">&gt;</span></span><span class="token plain-text"><br></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>hr</span><span                class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;</span>center</span><span                class="token punctuation">&gt;</span></span><span                class="token plain-text">nginx</span><span class="token tag"><span class="token tag"><span                class="token punctuation">&lt;/</span>center</span><span                class="token punctuation">&gt;</span></span><span class="token plain-text"><br></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span                class="token punctuation">&gt;</span></span><span class="token plain-text"><br></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span                class="token punctuation">&gt;</span></span><span class="token plain-text"><br></span><span aria-hidden="true"             class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><h5>四、显示通信过程</h5><p><code>-v</code> 参数可以显示一次 http 通信的整个过程，包括端口连接和 http request 头信息。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-bash"><code class="  language-bash">$ curl -v www.sina.com* Rebuilt URL to: www.sina.com/* Hostname was NOT found in DNS cache*   Trying 202.108.33.60...* Connected to www.sina.com (202.108.33.60) port 80 (#0)&gt; GET / HTTP/1.1&gt; User-Agent: curl/7.35.0&gt; Host: www.sina.com&gt; Accept: */*&gt;&lt; HTTP/1.1 301 Moved Permanently* Server nginx is not blacklisted&lt; Server: nginx&lt; Date: Tue, 23 Aug 2016 08:48:14 GMT&lt; Content-Type: text/html&lt; Location: http://www.sina.com.cn/&lt; Expires: Tue, 23 Aug 2016 08:50:14 GMT&lt; Cache-Control: max-age=120&lt; Age: 40&lt; Content-Length: 178&lt; X-Cache: HIT from xd33-81.sina.com.cn&lt;&lt;html&gt;&lt;head&gt;&lt;title&gt;301 Moved Permanently&lt;/title&gt;&lt;/head&gt;&lt;body bgcolor="white"&gt;&lt;center&gt;&lt;h1&gt;301 Moved Permanently&lt;/h1&gt;&lt;/center&gt;&lt;hr&gt;&lt;center&gt;nginx&lt;/center&gt;&lt;/body&gt;&lt;/html&gt;* Connection #0 to host www.sina.com left intact<span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div><p>如果觉得上面的信息还不够，那么下面的命令可以查看更详细的通信过程。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">$ curl <span            class="token operator">--</span>trace output<span class="token punctuation">.</span>txt www<span            class="token punctuation">.</span>sina<span class="token punctuation">.</span>com<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>或者</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">$ curl <span            class="token operator">--</span>trace<span class="token operator">-</span>ascii output<span            class="token punctuation">.</span>txt www<span class="token punctuation">.</span>sina<span            class="token punctuation">.</span>com<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>运行后，打开 output.txt 文件查看。</p><h5>五、发送表单信息</h5><p>发送表单信息有 GET 和 POST 两种方法。GET 方法相对简单，只要把数据附在网址后面就行。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-kotlin"><code class="  language-kotlin">$ curl example<span            class="token punctuation">.</span>com<span class="token operator">/</span>form<span            class="token punctuation">.</span>cgi<span class="token operator">?</span><span            class="token keyword">data</span><span            class="token operator">=</span>xxx<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>POST 方法必须把数据和网址分开，curl 就要用到 <code>--data</code> 或者 <code>-d</code> 参数。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-kotlin"><code class="  language-kotlin">$ curl <span            class="token operator">-</span>X POST <span class="token operator">--</span><span            class="token keyword">data</span> <span            class="token string">"data=xxx"</span> example<span class="token punctuation">.</span>com<span            class="token operator">/</span>form<span class="token punctuation">.</span>cgi<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>如果你的数据没有经过表单编码，还可以让 curl 为你编码，参数是 <code>--data-urlencode</code>。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-kotlin"><code class="  language-kotlin">$ curl <span            class="token operator">-</span>X POST<span class="token operator">--</span><span            class="token keyword">data</span><span            class="token operator">-</span>urlencode <span class="token string">"date=April 1"</span> example<span            class="token punctuation">.</span>com<span class="token operator">/</span>form<span            class="token punctuation">.</span>cgi<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><h5>六、HTTP动词</h5><p>curl 默认的 HTTP 动词是 GET，使用 <code>-X</code> 参数可以支持其他动词。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">$ curl <span            class="token operator">-</span><span class="token constant">X</span> <span            class="token constant">POST</span> www<span class="token punctuation">.</span>example<span            class="token punctuation">.</span>com$ curl <span class="token operator">-</span><span class="token constant">X</span> <span                class="token constant">DELETE</span> www<span class="token punctuation">.</span>example<span                class="token punctuation">.</span>com<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div><h5>七、User Agent字段</h5><p>这个字段是用来表示客户端的设备信息。服务器有时会根据这个字段，针对不同设备，返回不同格式的网页，比如手机版和桌面版。<br>    浏览器的 User Agent 是：</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-undefined"><code class="  language-undefined">Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>curl 可以这样模拟：</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">$ curl <span            class="token operator">--</span>user<span class="token operator">-</span>agent <span            class="token string">"[User Agent]"</span> <span class="token punctuation">[</span><span            class="token constant">URL</span><span class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><h5>八、cookie</h5><p>使用 <code>--cookie</code> 参数，可以让 curl 发送 cookie。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">$ curl <span            class="token operator">--</span>cookie <span class="token string">"name=xxx"</span> www<span            class="token punctuation">.</span>example<span class="token punctuation">.</span>com<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>至于具体的 cookie 的值，可以从 http response 头信息的 <code>Set-Cookie</code> 字段中得到。</p><h5>九、增加头信息</h5><p>有时需要在 http request 之中，自行增加一个头信息。<code>--header</code> 参数就可以起到这个作用。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-cpp"><code class="  language-cpp">$ curl <span            class="token operator">--</span>header <span class="token string">"Content-Type:application/json"</span> http<span            class="token operator">:</span><span class="token operator">/</span><span            class="token operator">/</span>example<span class="token punctuation">.</span>com<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><h5>十、HTTP认证</h5><p>有些网域需要 HTTP 认证，这时 curl 需要用到 <code>--user</code> 或者 <code>-u</code> 参数。</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-ruby"><code class="  language-ruby">$ curl <span            class="token operator">--</span>user name<span class="token symbol">:password</span> example<span            class="token punctuation">.</span>com<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><h5>附录 curl 命令完整的参数</h5><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-bash"><code class="  language-bash">$ curl --helpUsage: curl [options...] &lt;url&gt;Options: (H) means HTTP/HTTPS only, (F) means FTP only     --anyauth       Pick "any" authentication method (H) -a, --append        Append to target file when uploading (F/SFTP)     --basic         Use HTTP Basic Authentication (H)     --cacert FILE   CA certificate to verify peer against (SSL)     --capath DIR    CA directory to verify peer against (SSL) -E, --cert CERT[:PASSWD] Client certificate file and password (SSL)     --cert-type TYPE Certificate file type (DER/PEM/ENG) (SSL)     --ciphers LIST  SSL ciphers to use (SSL)     --compressed    Request compressed response (using deflate or gzip) -K, --config FILE   Specify which config file to read     --connect-timeout SECONDS  Maximum time allowed for connection -C, --continue-at OFFSET  Resumed transfer offset -b, --cookie STRING/FILE  String or file to read cookies from (H) -c, --cookie-jar FILE  Write cookies to this file after operation (H)     --create-dirs   Create necessary local directory hierarchy     --crlf          Convert LF to CRLF in upload     --crlfile FILE  Get a CRL list in PEM format from the given file -d, --data DATA     HTTP POST data (H)     --data-ascii DATA  HTTP POST ASCII data (H)     --data-binary DATA  HTTP POST binary data (H)     --data-urlencode DATA  HTTP POST data url encoded (H)     --delegation STRING GSS-API delegation permission     --digest        Use HTTP Digest Authentication (H)     --disable-eprt  Inhibit using EPRT or LPRT (F)     --disable-epsv  Inhibit using EPSV (F)     --dns-servers    DNS server addrs to use: 1.1.1.1;2.2.2.2     --dns-interface  Interface to use for DNS requests     --dns-ipv4-addr  IPv4 address to use for DNS requests, dot notation     --dns-ipv6-addr  IPv6 address to use for DNS requests, dot notation -D, --dump-header FILE  Write the headers to this file     --egd-file FILE  EGD socket path for random data (SSL)     --engine ENGINE  Crypto engine (SSL). "--engine list" for list -f, --fail          Fail silently (no output at all) on HTTP errors (H) -F, --form CONTENT  Specify HTTP multipart POST data (H)     --form-string STRING  Specify HTTP multipart POST data (H)     --ftp-account DATA  Account data string (F)     --ftp-alternative-to-user COMMAND  String to replace "USER [name]" (F)     --ftp-create-dirs  Create the remote dirs if not present (F)     --ftp-method [MULTICWD/NOCWD/SINGLECWD] Control CWD usage (F)     --ftp-pasv      Use PASV/EPSV instead of PORT (F) -P, --ftp-port ADR  Use PORT with given address instead of PASV (F)     --ftp-skip-pasv-ip Skip the IP address for PASV (F)     --ftp-pret      Send PRET before PASV (for drftpd) (F)     --ftp-ssl-ccc   Send CCC after authenticating (F)     --ftp-ssl-ccc-mode ACTIVE/PASSIVE  Set CCC mode (F)     --ftp-ssl-control Require SSL/TLS for ftp login, clear for transfer (F) -G, --get           Send the -d data with a HTTP GET (H) -g, --globoff       Disable URL sequences and ranges using &#123;&#125; and [] -H, --header LINE   Custom header to pass to server (H) -I, --head          Show document info only -h, --help          This help text     --hostpubmd5 MD5  Hex encoded MD5 string of the host public key. (SSH) -0, --http1.0       Use HTTP 1.0 (H)     --http1.1       Use HTTP 1.1 (H)     --http2.0       Use HTTP 2.0 (H)     --ignore-content-length  Ignore the HTTP Content-Length header -i, --include       Include protocol headers in the output (H/F) -k, --insecure      Allow connections to SSL sites without certs (H)     --interface INTERFACE  Specify network interface/address to use -4, --ipv4          Resolve name to IPv4 address -6, --ipv6          Resolve name to IPv6 address -j, --junk-session-cookies Ignore session cookies read from file (H)     --keepalive-time SECONDS  Interval between keepalive probes     --key KEY       Private key file name (SSL/SSH)     --key-type TYPE Private key file type (DER/PEM/ENG) (SSL)     --krb LEVEL     Enable Kerberos with specified security level (F)     --libcurl FILE  Dump libcurl equivalent code of this command line     --limit-rate RATE  Limit transfer speed to this rate -l, --list-only     List only mode (F/POP3)     --local-port RANGE  Force use of these local port numbers -L, --location      Follow redirects (H)     --location-trusted like --location and send auth to other hosts (H) -M, --manual        Display the full manual     --mail-from FROM  Mail from this address (SMTP)     --mail-rcpt TO  Mail to this/these addresses (SMTP)     --mail-auth AUTH  Originator address of the original email (SMTP)     --max-filesize BYTES  Maximum file size to download (H/F)     --max-redirs NUM  Maximum number of redirects allowed (H) -m, --max-time SECONDS  Maximum time allowed for the transfer     --metalink      Process given URLs as metalink XML file     --negotiate     Use HTTP Negotiate Authentication (H) -n, --netrc         Must read .netrc for user name and password     --netrc-optional Use either .netrc or URL; overrides -n     --netrc-file FILE  Set up the netrc filename to use -N, --no-buffer     Disable buffering of the output stream     --no-keepalive  Disable keepalive use on the connection     --no-sessionid  Disable SSL session-ID reusing (SSL)     --noproxy       List of hosts which do not use proxy     --ntlm          Use HTTP NTLM authentication (H)     --oauth2-bearer TOKEN  OAuth 2 Bearer Token (IMAP, POP3, SMTP) -o, --output FILE   Write output to &lt;file&gt; instead of stdout     --pass PASS     Pass phrase for the private key (SSL/SSH)     --post301       Do not switch to GET after following a 301 redirect (H)     --post302       Do not switch to GET after following a 302 redirect (H)     --post303       Do not switch to GET after following a 303 redirect (H) -#, --progress-bar  Display transfer progress as a progress bar     --proto PROTOCOLS  Enable/disable specified protocols     --proto-redir PROTOCOLS  Enable/disable specified protocols on redirect -x, --proxy [PROTOCOL://]HOST[:PORT] Use proxy on given port     --proxy-anyauth Pick "any" proxy authentication method (H)     --proxy-basic   Use Basic authentication on the proxy (H)     --proxy-digest  Use Digest authentication on the proxy (H)     --proxy-negotiate Use Negotiate authentication on the proxy (H)     --proxy-ntlm    Use NTLM authentication on the proxy (H) -U, --proxy-user USER[:PASSWORD]  Proxy user and password     --proxy1.0 HOST[:PORT]  Use HTTP/1.0 proxy on given port -p, --proxytunnel   Operate through a HTTP proxy tunnel (using CONNECT)     --pubkey KEY    Public key file name (SSH) -Q, --quote CMD     Send command(s) to server before transfer (F/SFTP)     --random-file FILE  File for reading random data from (SSL) -r, --range RANGE   Retrieve only the bytes within a range     --raw           Do HTTP "raw", without any transfer decoding (H) -e, --referer       Referer URL (H) -J, --remote-header-name Use the header-provided filename (H) -O, --remote-name   Write output to a file named as the remote file     --remote-name-all Use the remote file name for all URLs -R, --remote-time   Set the remote file's time on the local output -X, --request COMMAND  Specify request command to use     --resolve HOST:PORT:ADDRESS  Force resolve of HOST:PORT to ADDRESS     --retry NUM   Retry request NUM times if transient problems occur     --retry-delay SECONDS When retrying, wait this many seconds between each     --retry-max-time SECONDS  Retry only within this period     --sasl-ir       Enable initial response in SASL authentication -S, --show-error    Show error. With -s, make curl show errors when they occur -s, --silent        Silent mode. Don't output anything     --socks4 HOST[:PORT]  SOCKS4 proxy on given host + port     --socks4a HOST[:PORT]  SOCKS4a proxy on given host + port     --socks5 HOST[:PORT]  SOCKS5 proxy on given host + port     --socks5-hostname HOST[:PORT] SOCKS5 proxy, pass host name to proxy     --socks5-gssapi-service NAME  SOCKS5 proxy service name for gssapi     --socks5-gssapi-nec  Compatibility with NEC SOCKS5 server -Y, --speed-limit RATE  Stop transfers below speed-limit for 'speed-time' secs -y, --speed-time SECONDS  Time for trig speed-limit abort. Defaults to 30     --ssl           Try SSL/TLS (FTP, IMAP, POP3, SMTP)     --ssl-reqd      Require SSL/TLS (FTP, IMAP, POP3, SMTP) -2, --sslv2         Use SSLv2 (SSL) -3, --sslv3         Use SSLv3 (SSL)     --ssl-allow-beast Allow security flaw to improve interop (SSL)     --stderr FILE   Where to redirect stderr. - means stdout     --tcp-nodelay   Use the TCP_NODELAY option -t, --telnet-option OPT=VAL  Set telnet option     --tftp-blksize VALUE  Set TFTP BLKSIZE option (must be &gt;512) -z, --time-cond TIME  Transfer based on a time condition -1, --tlsv1         Use TLSv1 (SSL)     --trace FILE    Write a debug trace to the given file     --trace-ascii FILE  Like --trace but without the hex output     --trace-time    Add time stamps to trace/verbose output     --tr-encoding   Request compressed transfer encoding (H) -T, --upload-file FILE  Transfer FILE to destination     --url URL       URL to work with -B, --use-ascii     Use ASCII/text transfer -u, --user USER[:PASSWORD][;OPTIONS]  Server user, password and login options     --tlsuser USER  TLS username     --tlspassword STRING TLS password     --tlsauthtype STRING  TLS authentication type (default SRP) -A, --user-agent STRING  User-Agent to send to server (H) -v, --verbose       Make the operation more talkative -V, --version       Show version number and quit -w, --write-out FORMAT  What to output after completion     --xattr        Store metadata in extended file attributes -q                 If used as the first parameter disables .curlrc<pre><code>&lt;/code&gt;&lt;/pre&gt;</code></pre></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于Epoll的使用详解</title>
      <link href="python/tornado/epoll/"/>
      <url>python/tornado/epoll/</url>
      
        <content type="html"><![CDATA[<p>本文转自:<a href="https://www.jianshu.com/p/ee381d365a29">https://www.jianshu.com/p/ee381d365a29</a></p><blockquote>    <p>作者: 大呀大帝国 &lt;/br&gt;<br>        <a href="https://link.jianshu.com?t=mailto:email:drnijq@126.com" target="_blank" rel="nofollow">email:drnijq@126.com</a>    </p></blockquote><h2>1.Epoll简介</h2><p>EPOLL 的API用来执行类似poll()的任务。能够用于检测在多个文件描述符中任何IO可用的情况。Epoll API可以用于边缘触发(edge-triggered)和水平触发(level-triggered),    同时epoll可以检测更多的文件描述符。以下的系统调用函数提供了创建和管理epoll实例：</p><ul>    <li>epoll_create() 可以创建一个epoll实例并返回相应的文件描述符(epoll_create1() 扩展了epoll_create() 的功能)。</li>    <li>注册相关的文件描述符使用epoll_ctl()</li>    <li>epoll_wait() 可以用于等待IO事件。如果当前没有可用的事件，这个函数会阻塞调用线程。</li></ul><p><strong>边缘触发(edge-triggered 简称ET)和水平触发(level-triggered 简称LT)：</strong></p><p>epoll的事件派发接口可以运行在两种模式下：边缘触发(edge-triggered)和水平触发(level-triggered)，两种模式的区别请看下面,我们先假设下面的情况：</p><ol>    <li>一个代表管道读取的文件描述符已经注册到epoll实例上了。</li>    <li>在管道的写入端写入了2kb的数据。</li>    <li>epoll_wait 返回一个可用的rfd文件描述符。</li>    <li>从管道读取了1kb的数据。</li>    <li>调用epoll_wait 完成。</li></ol><p>如果rfd被设置了ET，在调用完第五步的epool_wait    后会被挂起，尽管在缓冲区还有可以读取的数据，同时另外一段的管道还在等待发送完毕的反馈。这是因为ET模式下只有文件描述符发生改变的时候，才会派发事件。所以第五步操作，可能会去等待已经存在缓冲区的数据。在上面的例子中，一个事件在第二步被创建，再第三步中被消耗，由于第四步中没有读取完缓冲区，第五步中的epoll_wait可能会一直被阻塞下去。</p><p>下面情况下推荐使用ET模式:</p><ol>    <li>使用非阻塞的IO。</li>    <li>epoll_wait() 只需要在read或者write返回的时候。</li></ol><p>相比之下，当我们使用LT的时候（默认）,epoll会比poll更简单更快速，而且我们可以使用在任何一个地方。</p><h2>2.API介绍</h2><p>先简单的看下EPOLL的API</p><h3>2.1 创建epoll</h3><hr><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-c"><code class="c  language-c"><span class="token macro property">#<span            class="token directive keyword">include</span> <span            class="token string">&lt;sys/epoll.h&gt;</span></span><p><span class="token keyword">int</span> <span class="token function">epoll_create</span><span                class="token punctuation">(</span><span class="token keyword">int</span> size<span                class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">int</span> <span class="token function">epoll_create1</span><span class="token punctuation">(</span><span                class="token keyword">int</span> flags<span class="token punctuation">)</span><span                class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>epoll_create() 可以创建一个epoll实例。在linux 内核版本大于2.6.8 后，这个<strong><em>size</em></strong> 参数就被弃用了，但是传入的值必须大于0。</p><blockquote>    <p>在 epoll_create () 的最初实现版本时， size参数的作用是创建epoll实例时候告诉内核需要使用多少个文件描述符。内核会使用 size 的大小去申请对应的内存(如果在使用的时候超过了给定的size，        内核会申请更多的空间)。现在，这个size参数不再使用了（内核会动态的申请需要的内存）。但要注意的是，这个size必须要大于0，为了兼容旧版的linux 内核的代码。</p></blockquote><p>epoll_create() 会返回新的epoll对象的文件描述符。这个文件描述符用于后续的epoll操作。如果不需要使用这个描述符，请使用close关闭。</p><p>epoll_create1()    如果<strong><em>flags</em></strong>的值是0，epoll_create1()等同于epoll_create()除了过时的size被遗弃了。当然<strong><em>flasg</em></strong>可以使用    EPOLL_CLOEXEC，请查看 open() 中的O_CLOEXEC来查看 EPOLL_CLOEXEC有什么用。</p><p><strong><em>返回值:</em></strong> 如果执行成功，返回一个非负数(实际为文件描述符), 如果执行失败，会返回-1，具体原因请查看error.</p><h3>2.2 设置epoll事件</h3><hr><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-c"><code class="c++ ++  language-c"><span class="token macro property">#<span            class="token directive keyword">include</span> <span            class="token string">&lt;sys/epoll.h&gt;</span></span><p><span class="token keyword">int</span> <span class="token function">epoll_ctl</span><span                class="token punctuation">(</span><span class="token keyword">int</span> epfd<span                class="token punctuation">,</span> <span class="token keyword">int</span> op<span                class="token punctuation">,</span> <span class="token keyword">int</span> fd<span                class="token punctuation">,</span> <span class="token keyword">struct</span> <span                class="token class-name">epoll_event</span> <span class="token operator">*</span>event<span                class="token punctuation">)</span><span class="token punctuation">;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></p></div><p>    这个系统调用能够控制给定的文件描述符<strong><em>epfd</em></strong>指向的epoll实例，<strong><em>op</em></strong>是添加事件的类型，<strong><em>fd</em></strong>是目标文件描述符。</p><p>有效的op值有以下几种：</p><ul>    <li>EPOLL_CTL_ADD        在<strong><em>epfd</em></strong>中注册指定的fd文件描述符并能把<strong><em>event</em></strong>和<strong><em>fd</em></strong>关联起来。    </li>    <li>EPOLL_CTL_MOD 改变*** fd<strong><em>和</em></strong>evetn***之间的联系。</li>    <li>EPOLL_CTL_DEL        从指定的<strong><em>epfd</em></strong>中删除<strong><em>fd</em></strong>文件描述符。在这种模式中<strong><em>event</em></strong>是被忽略的，并且为可以等于NULL。    </li></ul><p><strong><em>event</em></strong>这个参数是用于关联制定的<strong><em>fd</em></strong>文件描述符的。它的定义如下：</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-c"><code class="c  language-c"><span            class="token keyword">typedef</span> <span class="token keyword">union</span> epoll_data <span            class="token punctuation">&#123;</span>    <span class="token keyword">void</span>        <span class="token operator">*</span>ptr<span                class="token punctuation">;</span>    <span class="token keyword">int</span>          fd<span class="token punctuation">;</span>    uint32_t     u32<span class="token punctuation">;</span>    uint64_t     u64<span class="token punctuation">;</span><span class="token punctuation">&#125;</span> epoll_data_t<span class="token punctuation">;</span><p><span class="token keyword">struct</span> <span class="token class-name">epoll_event</span> <span                class="token punctuation">&#123;</span><br>    uint32_t     events<span class="token punctuation">;</span>      <span                class="token comment">/* Epoll events <em>/</span><br>    epoll_data_t data<span class="token punctuation">;</span>        <span class="token comment">/</em> User data variable */</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p><strong><em>events</em></strong>这个参数是一个字节的掩码构成的。下面是可以用的事件：</p><ul>    <li>EPOLLIN - 当关联的文件可以执行 read ()操作时。</li>    <li>EPOLLOUT - 当关联的文件可以执行 write ()操作时。</li>    <li>EPOLLRDHUP - (从 linux 2.6.17 开始)当socket关闭的时候，或者半关闭写段的(当使用边缘触发的时候，这个标识在写一些测试代码去检测关闭的时候特别好用)</li>    <li>EPOLLPRI - 当 read ()能够读取紧急数据的时候。</li>    <li>EPOLLERR - 当关联的文件发生错误的时候，epoll_wait() 总是会等待这个事件，并不是需要必须设置的标识。</li>    <li>EPOLLHUP - 当指定的文件描述符被挂起的时候。epoll_wait()        总是会等待这个事件，并不是需要必须设置的标识。当socket从某一个地方读取数据的时候(管道或者socket),这个事件只是标识出这个已经读取到最后了(EOF)。所有的有效数据已经被读取完毕了，之后任何的读取都会返回0(EOF)。    </li>    <li>EPOLLET - 设置指定的文件描述符模式为边缘触发，默认的模式是水平触发。</li>    <li>EPOLLONESHOT - (从 linux 2.6.17 开始)设置指定文件描述符为单次模式。这意味着，在设置后只会有一次从epoll_wait() 中捕获到事件，之后你必须要重新调用 epoll_ctl()        重新设置。    </li></ul><p><strong><em>返回值：</em></strong>如果成功，返回0。如果失败，会返回-1， <strong><em>errno</em></strong>将会被设置</p><p>有以下几种错误：</p><ul>    <li>EBADF - <strong><em>epfd</em></strong> 或者 <strong><em>fd</em></strong> 是无效的文件描述符。</li>    <li>EEXIST - <strong><em>op</em></strong>是EPOLL_CTL_ADD，同时 <strong><em>fd</em></strong> 在之前，已经被注册到epoll中了。</li>    <li>EINVAL -        <strong><em>epfd</em></strong>不是一个epoll描述符。或者<strong><em>fd</em></strong>和<strong><em>epfd</em></strong>相同，或者<strong><em>op</em></strong>参数非法。    </li>    <li>ENOENT - <strong><em>op</em></strong>是EPOLL_CTL_MOD或者EPOLL_CTL_DEL，但是<strong><em>fd</em></strong>还没有被注册到epoll上。    </li>    <li>ENOMEM - 内存不足。</li>    <li>EPERM - 目标的<strong><em>fd</em></strong>不支持epoll。</li></ul><hr><h3>2.3 等待epoll事件</h3><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-c"><code class="c  language-c"><span class="token macro property">#<span            class="token directive keyword">include</span> <span            class="token string">&lt;sys/epoll.h&gt;</span></span><p><span class="token keyword">int</span> <span class="token function">epoll_wait</span><span                class="token punctuation">(</span><span class="token keyword">int</span> epfd<span                class="token punctuation">,</span> <span class="token keyword">struct</span> <span                class="token class-name">epoll_event</span> <span class="token operator">*</span>events<span                class="token punctuation">,</span><br>                      <span class="token keyword">int</span> maxevents<span class="token punctuation">,</span> <span                class="token keyword">int</span> timeout<span class="token punctuation">)</span><span                class="token punctuation">;</span></p><p><span class="token keyword">int</span> <span class="token function">epoll_pwait</span><span                class="token punctuation">(</span><span class="token keyword">int</span> epfd<span                class="token punctuation">,</span> <span class="token keyword">struct</span> <span                class="token class-name">epoll_event</span> <span class="token operator"><em></span>events<span                class="token punctuation">,</span><br>                      <span class="token keyword">int</span> maxevents<span class="token punctuation">,</span> <span                class="token keyword">int</span> timeout<span class="token punctuation">,</span><br>                      <span class="token keyword">const</span> sigset_t <span                class="token operator"></em></span>sigmask<span class="token punctuation">)</span><span                class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>epoll_wait    这个系统调用是用来等待<strong><em>epfd</em></strong>中的事件。<strong><em>events</em></strong>指向调用者可以使用的事件的内存区域。<strong><em>maxevents</em></strong>告知内核有多少个events，必须要大于0.</p><p><strong><em>timeout</em></strong>这个参数是用来制定epoll_wait 会阻塞多少毫秒，会一直阻塞到下面几种情况：</p><ol>    <li>一个文件描述符触发了事件。</li>    <li>被一个信号处理函数打断，或者timeout超时。</li></ol><p>当<strong><em>timeout</em></strong>等于-1的时候这个函数会无限期的阻塞下去，当<strong><em>timeout</em></strong>等于0的时候，就算没有任何事件，也会立刻返回。</p><p>struct epoll_event 如下定义:</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-c"><code class="c  language-c"><span            class="token keyword">typedef</span> <span class="token keyword">union</span> epoll_data <span            class="token punctuation">&#123;</span>    <span class="token keyword">void</span>    <span class="token operator">*</span>ptr<span                class="token punctuation">;</span>    <span class="token keyword">int</span>      fd<span class="token punctuation">;</span>    uint32_t u32<span class="token punctuation">;</span>    uint64_t u64<span class="token punctuation">;</span><span class="token punctuation">&#125;</span> epoll_data_t<span class="token punctuation">;</span><p><span class="token keyword">struct</span> <span class="token class-name">epoll_event</span> <span                class="token punctuation">&#123;</span><br>    uint32_t     events<span class="token punctuation">;</span>    <span class="token comment">/* Epoll events <em>/</span><br>    epoll_data_t data<span class="token punctuation">;</span>      <span                class="token comment">/</em> User data variable */</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><p>每次epoll_wait() 返回的时候，会包含用户在epoll_ctl中设置的events。</p><p>还有一个系统调用epoll_pwait ()。epoll_pwait()和epoll_wait ()的关系就像select()和    pselect()的关系。和pselect()一样，epoll_pwait()可以让应用程序安全的等待知道某一个文件描述符就绪或者捕捉到信号。</p><p>下面的 epoll_pwait () 调用：</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-c"><code class="c  language-c">ready <span            class="token operator">=</span> <span class="token function">epoll_pwait</span><span            class="token punctuation">(</span>epfd<span class="token punctuation">,</span> <span            class="token operator">&amp;</span>events<span class="token punctuation">,</span> maxevents<span            class="token punctuation">,</span> timeout<span class="token punctuation">,</span> <span            class="token operator">&amp;</span>sigmask<span class="token punctuation">)</span><span            class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div><p>在内部等同于:</p><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-c"><code class="c  language-c"><span            class="token function">pthread_sigmask</span><span class="token punctuation">(</span>SIG_SETMASK<span            class="token punctuation">,</span> <span class="token operator">&amp;</span>sigmask<span            class="token punctuation">,</span> <span class="token operator">&amp;</span>origmask<span            class="token punctuation">)</span><span class="token punctuation">;</span>ready <span class="token operator">=</span> <span class="token function">epoll_wait</span><span                class="token punctuation">(</span>epfd<span class="token punctuation">,</span> <span                class="token operator">&amp;</span>events<span class="token punctuation">,</span> maxevents<span                class="token punctuation">,</span> timeout<span class="token punctuation">)</span><span                class="token punctuation">;</span><span class="token function">pthread_sigmask</span><span class="token punctuation">(</span>SIG_SETMASK<span                class="token punctuation">,</span> <span class="token operator">&amp;</span>origmask<span                class="token punctuation">,</span> <span class="token constant">NULL</span><span                class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div><p>如果 <strong><em>sigmask</em></strong>为NULL, epoll_pwait()等同于epoll_wait()。</p><p><strong><em>返回值：</em></strong>有多少个IO事件已经准备就绪。如果返回0说明没有IO事件就绪，而是timeout超时。遇到错误的时候，会返回-1，并设置 errno。</p><p>有以下几种错误:</p><ul>    <li>EBADF - <strong><em>epfd</em></strong>是无效的文件描述符</li>    <li>EFAULT - 指针<strong><em>events</em></strong>指向的内存没有访问权限</li>    <li>EINTR - 这个调用被信号打断。</li>    <li>EINVAL - <strong><em>epfd</em></strong>不是一个epoll的文件描述符，或者<strong><em>maxevents</em></strong>小于等于0</li></ul><h2>3. 官方demo</h2><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-c"><code class="c++ ++  language-c"><span class="token macro property">#<span            class="token directive keyword">define</span> MAX_EVENTS 10</span><span class="token keyword">struct</span> <span class="token class-name">epoll_event</span>  ev<span                class="token punctuation">,</span> events<span class="token punctuation">[</span>MAX_EVENTS<span                class="token punctuation">]</span><span class="token punctuation">;</span><span class="token keyword">int</span>         listen_sock<span class="token punctuation">,</span> conn_sock<span                class="token punctuation">,</span> nfds<span class="token punctuation">,</span> epollfd<span                class="token punctuation">;</span><p><span class="token comment">/* Code to set up listening socket, ‘listen_sock’,</p><ul><li>(socket(), bind(), listen()) omitted */</span></li></ul><p>epollfd <span class="token operator">=</span> <span class="token function">epoll_create1</span><span                class="token punctuation">(</span> <span class="token number">0</span> <span                class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">if</span> <span class="token punctuation">(</span> epollfd <span                class="token operator">==</span> <span class="token operator">-</span><span                class="token number">1</span> <span class="token punctuation">)</span><br><span class="token punctuation">&#123;</span><br>    <span class="token function">perror</span><span class="token punctuation">(</span> <span class="token string">“epoll_create1”</span> <span                class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token function">exit</span><span class="token punctuation">(</span> EXIT_FAILURE <span                class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span></p><p>ev<span class="token punctuation">.</span>events   <span class="token operator">=</span> EPOLLIN<span                class="token punctuation">;</span><br>ev<span class="token punctuation">.</span>data<span class="token punctuation">.</span>fd  <span                class="token operator">=</span> listen_sock<span class="token punctuation">;</span><br><span class="token keyword">if</span> <span class="token punctuation">(</span> <span                class="token function">epoll_ctl</span><span class="token punctuation">(</span> epollfd<span                class="token punctuation">,</span> EPOLL_CTL_ADD<span                class="token punctuation">,</span> listen_sock<span                class="token punctuation">,</span> <span class="token operator">&amp;</span>ev <span                class="token punctuation">)</span> <span class="token operator">==</span> <span                class="token operator">-</span><span class="token number">1</span> <span                class="token punctuation">)</span><br><span class="token punctuation">&#123;</span><br>    <span class="token function">perror</span><span class="token punctuation">(</span> <span class="token string">“epoll_ctl: listen_sock”</span> <span                class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token function">exit</span><span class="token punctuation">(</span> EXIT_FAILURE <span                class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span></p><p><span class="token keyword">for</span> <span class="token punctuation">(</span><span                class="token punctuation">;</span><span class="token punctuation">;</span> <span                class="token punctuation">)</span><br><span class="token punctuation">&#123;</span><br>    nfds <span class="token operator">=</span> <span class="token function">epoll_wait</span><span                class="token punctuation">(</span> epollfd<span class="token punctuation">,</span> events<span                class="token punctuation">,</span> MAX_EVENTS<span class="token punctuation">,</span> <span                class="token operator">-</span><span class="token number">1</span> <span                class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token keyword">if</span> <span class="token punctuation">(</span> nfds <span                class="token operator">==</span> <span class="token operator">-</span><span                class="token number">1</span> <span class="token punctuation">)</span><br>    <span class="token punctuation">&#123;</span><br>        <span class="token function">perror</span><span class="token punctuation">(</span> <span class="token string">“epoll_wait”</span> <span                class="token punctuation">)</span><span class="token punctuation">;</span><br>        <span class="token function">exit</span><span class="token punctuation">(</span> EXIT_FAILURE <span                class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token punctuation">&#125;</span></p><pre><code>&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; n &lt;span            class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; nfds&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;n &lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; events&lt;span            class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; listen_sock &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        conn_sock &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;accept&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; listen_sock&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span            class=&quot;token class-name&quot;&gt;sockaddr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;local&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;addrlen &lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; conn_sock &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span            class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;            &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span            class=&quot;token string&quot;&gt;&quot;accept&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; EXIT_FAILURE &lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;setnonblocking&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; conn_sock &lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        ev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;events   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; EPOLLIN &lt;span            class=&quot;token operator&quot;&gt;|&lt;/span&gt; EPOLLET&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        ev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd  &lt;span            class=&quot;token operator&quot;&gt;=&lt;/span&gt; conn_sock&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;epoll_ctl&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; epollfd&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EPOLL_CTL_ADD&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; conn_sock&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ev &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span            class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;            &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span            class=&quot;token string&quot;&gt;&quot;epoll_ctl: conn_sock&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; EXIT_FAILURE &lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;do_use_fd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; events&lt;span            class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd &lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;</code></pre><p><span class="token punctuation">}</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p></div><h2>4.完整可运行的DEMO</h2><div class="_2Uzcx_">    <button class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy">        <svg viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"             fill="currentColor" aria-hidden="true">            <path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path>        </svg>    </i></button>    <pre class="line-numbers  language-cpp"><code class="cpp  language-cpp"><span            class="token macro property">#<span class="token directive keyword">include</span> <span            class="token string">&lt;stdio.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;sys/epoll.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;sys/socket.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;sys/types.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;netinet/in.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;arpa/inet.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;fcntl.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;unistd.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;netdb.h&gt;</span></span><span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string">&lt;errno.h&gt;</span></span><p><span class="token macro property">#<span class="token directive keyword">define</span> MAX_EVENT 20</span><br><span class="token macro property">#<span class="token directive keyword">define</span> READ_BUF_LEN 256</span></p><p><span class="token comment">/**</p><ul><li><p>设置 file describe 为非阻塞模式</p></li><li><p>@param fd 文件描述</p></li><li><p>@return 返回0成功，返回-1失败</p></li><li><p>/</span><br><span class="token keyword">static</span> <span class="token keyword">int</span> make_socket_non_blocking &lt;span</p><pre><code>          class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; fd&lt;span          class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;</code></pre><p>  <span class="token keyword">int</span> flags<span class="token punctuation">,</span> s&lt;span</p><pre><code>          class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p>  <span class="token comment">// 获取当前flag</span><br>  flags <span class="token operator">=</span> <span class="token function">fcntl</span>&lt;span</p><pre><code>          class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; F_GETFL&lt;span          class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span          class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p>  <span class="token keyword">if</span> <span class="token punctuation">(</span>&lt;span</p><pre><code>          class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span          class=&quot;token operator&quot;&gt;==&lt;/span&gt; flags&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span          class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Get fd status&quot;&lt;/span&gt;&lt;span          class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span          class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p>  <span class="token punctuation">}</span></p><p>  flags <span class="token operator">|=</span> O_NONBLOCK<span class="token punctuation">;</span></p><p>  <span class="token comment">// 设置flag</span><br>  s <span class="token operator">=</span> <span class="token function">fcntl</span>&lt;span</p><pre><code>          class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; F_SETFL&lt;span          class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flags&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span          class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p>  <span class="token keyword">if</span> <span class="token punctuation">(</span>&lt;span</p><pre><code>          class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span          class=&quot;token operator&quot;&gt;==&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span          class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Set fd status&quot;&lt;/span&gt;&lt;span          class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span          class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p>  <span class="token punctuation">}</span><br>  <span class="token keyword">return</span> <span class="token number">0</span>&lt;span</p><pre><code>          class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p><span class="token punctuation">}</span></p></li></ul><p><span class="token keyword">int</span> <span class="token function">main</span><span                class="token punctuation">(</span><span class="token punctuation">)</span> <span                class="token punctuation">{</span><br>    <span class="token comment">// epoll 实例 file describe</span><br>    <span class="token keyword">int</span> epfd <span class="token operator">=</span> <span                class="token number">0</span><span class="token punctuation">;</span><br>    <span class="token keyword">int</span> listenfd <span class="token operator">=</span> <span                class="token number">0</span><span class="token punctuation">;</span><br>    <span class="token keyword">int</span> result <span class="token operator">=</span> <span                class="token number">0</span><span class="token punctuation">;</span><br>    <span class="token keyword">struct</span> <span class="token class-name">epoll_event</span> ev<span                class="token punctuation">,</span> event<span class="token punctuation">[</span>MAX_EVENT<span                class="token punctuation">]</span><span class="token punctuation">;</span><br>    <span class="token comment">// 绑定的地址</span><br>    <span class="token keyword">const</span> <span class="token keyword">char</span> <span                class="token operator">*</span> <span class="token keyword">const</span> local_addr <span                class="token operator">=</span> <span class="token string">“192.168.0.45”</span><span                class="token punctuation">;</span><br>    <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> server_addr <span                class="token operator">=</span> <span class="token punctuation">{</span> <span                class="token number">0</span> <span                class="token punctuation">}</span><span class="token punctuation">;</span></p><pre><code>listenfd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;socket&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AF_INET&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SOCK_STREAM&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; listenfd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Open listen socket&quot;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span            class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;/* Enable address reuse */&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; on &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 打开 socket 端口复用, 防止测试的时候出现 Address already in use&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setsockopt&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; listenfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SOL_SOCKET&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SO_REUSEADDR&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;on&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span            class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;on&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    perror &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Set socket&quot;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;server_addr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sin_family &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; AF_INET&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;inet_aton &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;local_addr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;server_addr&lt;span            class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sin_addr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;server_addr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sin_port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token function&quot;&gt;htons&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;listenfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span            class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;sockaddr&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;server_addr&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;server_addr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bind port&quot;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_socket_non_blocking&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;listenfd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;listenfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span            class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Start listen&quot;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 创建epoll实例&lt;/span&gt;epfd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;epoll_create1&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; epfd&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Create epoll instance&quot;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;ev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd &lt;span            class=&quot;token operator&quot;&gt;=&lt;/span&gt; listenfd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;ev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;events &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; EPOLLIN &lt;span            class=&quot;token operator&quot;&gt;|&lt;/span&gt; EPOLLET &lt;span class=&quot;token comment&quot;&gt;/* 边缘触发选项。 */&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 设置epoll的事件&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;epoll_ctl&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;epfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EPOLL_CTL_ADD&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; listenfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ev&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Set epoll_ctl&quot;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; wait_count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 等待事件&lt;/span&gt;    wait_count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;epoll_wait&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;epfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; event&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MAX_EVENT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; wait_count&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;uint32_t&lt;/span&gt; events &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span            class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;events&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// IP地址缓存&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; host_buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;NI_MAXHOST&lt;span            class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// PORT缓存&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; port_buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;NI_MAXSERV&lt;span            class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; __result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// 判断epoll是否发生错误&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; events &lt;span            class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; EPOLLERR &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; events &lt;span            class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; EPOLLHUP &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; events &lt;span            class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; EPOLLIN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;            &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token string&quot;&gt;&quot;Epoll has error\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            close &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span            class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span            class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span            class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;listenfd &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span            class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span            class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;// listen的 file describe 事件触发， accpet事件&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt; &lt;span            class=&quot;token comment&quot;&gt;// 由于采用了边缘触发模式，这里需要使用循环&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span            class=&quot;token class-name&quot;&gt;sockaddr&lt;/span&gt; in_addr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                socklen_t in_addr_len &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;in_addr&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; accp_fd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token function&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;listenfd&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;in_addr&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;in_addr_len&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; accp_fd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                    &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token string&quot;&gt;&quot;Accept&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;                __result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getnameinfo&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;in_addr&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;in_addr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                                       host_buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;host_buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;host_buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span            class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                                       port_buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port_buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port_buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span            class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                                       NI_NUMERICHOST &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; NI_NUMERICSERV&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;!&lt;/span&gt; __result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token string&quot;&gt;&quot;New connection: host = %s, port = %s\n&quot;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; host_buf&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port_buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;                __result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token function&quot;&gt;make_socket_non_blocking&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;accp_fd&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; __result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;                ev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd &lt;span            class=&quot;token operator&quot;&gt;=&lt;/span&gt; accp_fd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                ev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;events &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; EPOLLIN &lt;span            class=&quot;token operator&quot;&gt;|&lt;/span&gt; EPOLLET&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;// 为新accept的 file describe 设置epoll事件&lt;/span&gt;                __result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;epoll_ctl&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;epfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EPOLL_CTL_ADD&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; accp_fd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ev&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; __result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                    &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token string&quot;&gt;&quot;epoll_ctl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;// 其余事件为 file describe 可以读取&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;// 因为采用边缘触发，所以这里需要使用循环。如果不使用循环，程序并不能完全读取到缓存区里面的数据。&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                ssize_t result_len &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;READ_BUF_LEN&lt;span            class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                result_len &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span            class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span            class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buf&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span            class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span            class=&quot;token operator&quot;&gt;==&lt;/span&gt; result_len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EAGAIN &lt;span            class=&quot;token operator&quot;&gt;!=&lt;/span&gt; errno&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                        perror &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Read data&quot;&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                        done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span            class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token operator&quot;&gt;!&lt;/span&gt; result_len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span            class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                    done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;                &lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;STDOUT_FILENO&lt;span            class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result_len&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;done&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;                &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span            class=&quot;token string&quot;&gt;&quot;Closed connection\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                close &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span            class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span            class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;close &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;epfd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p><span class="token punctuation">}</span><br></code></pre></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tornado学习笔记day01</title>
      <link href="python/tornado/tornado-note1/"/>
      <url>python/tornado/tornado-note1/</url>
      
        <content type="html"><![CDATA[<h2 id="tornado的安装"><a href="#tornado的安装" class="headerlink" title="tornado的安装"></a>tornado的安装</h2><p>这里我使用的是<a href="https://victorfengming.gitee.io/blog/python-venv/">虚拟环境</a>中的<a href="https://victorfengming.gitee.io/blog/python-install-pip/">pip</a>安装,配合<a href="https://victorfengming.gitee.io/blog/pip-conf/">清华大学镜像源</a>安装的</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install tornado -i https://pypi.tuna.tsinghua.edu.cn/simple</span><br></pre></td></tr></table></figure><h2 id="我的第一个tornado程序"><a href="#我的第一个tornado程序" class="headerlink" title="我的第一个tornado程序"></a>我的第一个tornado程序</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="keyword">import</span> tornado.ioloop</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">tornado.web.RequestHandler</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    主页处理函数</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;hello tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app = tornado.web.Application([(<span class="string">r&quot;/&quot;</span>,IndexHandler)])</span><br><span class="line">    app.listen(<span class="number">8000</span>)</span><br><span class="line">    tornado.ioloop.IOLoop.current().start()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在tornado中,直接执行就行,不用加任何参数也OK</p><p>因为在里面已经帮你创建了一个服务器了</p><h2 id="初始tornado"><a href="#初始tornado" class="headerlink" title="初始tornado"></a>初始tornado</h2><h3 id="什么是tornado"><a href="#什么是tornado" class="headerlink" title="什么是tornado"></a>什么是tornado</h3><p>全称tornado web server ,是一种web服务器软件的开源版本</p><h3 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h3><p>作为web 框架,是一个轻量级的web框架,类似于另一个python web 框架 web.py,其拥有一部非阻塞IO的处理方式</p><p>作为 web 服务器,tornado 有较为出色的抗负载能力,官方用nginx反向dialing的方式部署tornado和其他python web 应用框架进行对比,结果最大浏览量超过第二名近40%</p><h3 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h3><ul><li>用户量大,高并发</li><li>大量的HTTP持久连接<ul><li>使用同一个TCP连接来发送和接收多个HTTP请求/应答,而不是为每一个新的请求/应答打开新的连接方式</li><li>对于HTTP1.0,可以在请求的包头(Header)中添加Connection: Keep-Alive。</li><li>对于HTTP 1.1，所有的连接默认都是持久连接。</li></ul></li></ul><h3 id="C10K"><a href="#C10K" class="headerlink" title="C10K"></a>C10K</h3><p>上面的高并发的为题,通常用C10K这一概念来描述.C10K-Concurrently handling ten thousand connections ,即并发10000个连接,对于单台服务器而言,根本无法承担,而采用多台服务器分布式又意味着高昂的成本</p><h3 id="性能"><a href="#性能" class="headerlink" title="性能"></a>性能</h3><p>tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有非常高性能的解决方案(服务器与框架的集合体) </p><h3 id="tornado和django对比"><a href="#tornado和django对比" class="headerlink" title="tornado和django对比"></a>tornado和django对比</h3><h4 id="django"><a href="#django" class="headerlink" title="django"></a>django</h4><p>django是走大而全的方向,注重的是高效开发,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构,以及全功能的管理后台</p><p>Django提供的方便,也意味着Django内置的ORM跟框架内的其他模板耦合程度高,应用程序必须使用Django内置的ORM,否则就不能享受到框架内提供的种种基于其ORM的便利</p><p>特点:</p><ul><li>session功能</li><li>后台管理</li><li>ORM<h4 id="tornado"><a href="#tornado" class="headerlink" title="tornado"></a>tornado</h4>tornado走的是少而精的方向,注重的是性能的优越,它最出名的是异步非阻塞的设计方式<br>特点</li><li>HTTP服务器</li><li>异步编程</li><li>webSockets</li></ul><h3 id="第一个程序的批注解释1-0"><a href="#第一个程序的批注解释1-0" class="headerlink" title="第一个程序的批注解释1.0"></a>第一个程序的批注解释1.0</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">tornado的基础web框架模块</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> tornado.ioloop</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">tornado的核心IO循环模块,</span></span><br><span class="line"><span class="string">封装了Linux的epoll和BSD的kqueue</span></span><br><span class="line"><span class="string">这个是tornado高效的基础</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 业务处理类</span></span><br><span class="line"><span class="comment"># 类比Django的视图</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">tornado.web.RequestHandler</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    主页处理函数</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 处理GET请求的</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        这个get不是随便写的,是框架提前定义好的</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 对应HTTP请求的方法</span></span><br><span class="line">        <span class="comment"># 给浏览器响应信息</span></span><br><span class="line">        self.write(<span class="string">&quot;hello tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># 这个路由和django差不多,只不过这个调用的是一个类</span></span><br><span class="line">    <span class="comment"># 实例化app应用对象</span></span><br><span class="line">    <span class="comment"># Application是tornado框架的核心,与服务器对接的接口</span></span><br><span class="line">    <span class="comment"># 里面保存了路由映射表,有一个listen方法,用来创建一个HTTP服务器的实例,并绑定了端口</span></span><br><span class="line">    app = tornado.web.Application([(<span class="string">r&quot;/&quot;</span>,IndexHandler)])</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 这个只是绑定在8000端口,注意:并没有进行监听奥</span></span><br><span class="line">    app.listen(<span class="number">8000</span>)</span><br><span class="line">    <span class="comment"># tornado的启动方式</span></span><br><span class="line">    <span class="comment"># IOLoop.current():返回当前线程的IO实例</span></span><br><span class="line">    <span class="comment"># IOLoop.start(): 启动实例的IO循环,同时开启监听</span></span><br><span class="line">    tornado.ioloop.IOLoop.current().start()</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="第一个程序的批注解释2-0"><a href="#第一个程序的批注解释2-0" class="headerlink" title="第一个程序的批注解释2.0"></a>第一个程序的批注解释2.0</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">tornado的基础web框架模块</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> tornado.ioloop</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">tornado的核心IO循环模块,</span></span><br><span class="line"><span class="string">封装了Linux的epoll和BSD的kqueue</span></span><br><span class="line"><span class="string">这个是tornado高效的基础</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 引入httpserver模块</span></span><br><span class="line"><span class="keyword">import</span> tornado.httpserver</span><br><span class="line"></span><br><span class="line"><span class="comment"># 业务处理类</span></span><br><span class="line"><span class="comment"># 类比Django的视图</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">tornado.web.RequestHandler</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    主页处理函数</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 处理GET请求的</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        这个get不是随便写的,是框架提前定义好的</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 对应HTTP请求的方法</span></span><br><span class="line">        <span class="comment"># 给浏览器响应信息</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># 这个路由和django差不多,只不过这个调用的是一个类</span></span><br><span class="line">    <span class="comment"># 实例化app应用对象</span></span><br><span class="line">    <span class="comment"># Application是tornado框架的核心,与服务器对接的接口</span></span><br><span class="line">    <span class="comment"># 里面保存了路由映射表,有一个listen方法,用来创建一个HTTP服务器的实例,并绑定了端口</span></span><br><span class="line">    app = tornado.web.Application([(<span class="string">r&quot;/&quot;</span>,IndexHandler)])</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 这个只是绑定在8000端口,注意:并没有进行监听奥</span></span><br><span class="line">    <span class="comment"># app.listen(8000)</span></span><br><span class="line">    <span class="comment"># 实例化一个http服务器对象</span></span><br><span class="line">    httpServer = tornado.httpserver.HTTPServer(app)</span><br><span class="line">    <span class="comment"># 绑定端口</span></span><br><span class="line">    httpServer.listen(<span class="number">8000</span>)</span><br><span class="line">    <span class="comment"># 这个和上面的listen可不一样,两个对象的方法,不同</span></span><br><span class="line">    <span class="comment"># 说白了,上面的一行,相当于我们这个两行代码的和</span></span><br><span class="line">    <span class="comment"># 这也就是tornado不用像Django那样加上runserver参数启动服务器了</span></span><br><span class="line">    <span class="comment"># 以为代码中写了</span></span><br><span class="line"></span><br><span class="line">    tornado.ioloop.IOLoop.current().start()</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="第一个程序的批注解释3-0"><a href="#第一个程序的批注解释3-0" class="headerlink" title="第一个程序的批注解释3.0"></a>第一个程序的批注解释3.0</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="keyword">import</span> tornado.ioloop</span><br><span class="line"><span class="keyword">import</span> tornado.httpserver</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">tornado.web.RequestHandler</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    主页处理函数</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        这个get不是随便写的,是框架提前定义好的</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app = tornado.web.Application([(<span class="string">r&quot;/&quot;</span>,IndexHandler)])</span><br><span class="line">    </span><br><span class="line"></span><br><span class="line">    httpServer = tornado.httpserver.HTTPServer(app)</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># httpServer.listen(8000)</span></span><br><span class="line">    <span class="comment"># 这里不用listen了,我们用bind</span></span><br><span class="line">    <span class="comment"># 将服务器绑定到指定的端口上</span></span><br><span class="line">    httpServer.bind(<span class="number">8000</span>)</span><br><span class="line">    <span class="comment"># 这里我写几个就开几个进程</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    默认开启一个进程</span></span><br><span class="line"><span class="string">    如果大于0,开启多个进程</span></span><br><span class="line"><span class="string">    值为none或者小于等于0的话,就开启对应硬件机器CPU核心数的子进程</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    httpServer.start(<span class="number">5</span>)</span><br><span class="line">    <span class="comment"># 这个bind和start加一起就相当于 httpServer.listen(8000)了</span></span><br><span class="line">    <span class="comment"># 近期你可以多些一点,以为你要对于创建服务器的流程有一个了解,以后随便写</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># app.listen() 只能在单继承模式中使用</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    多进程: 虽然tornado给我们提供了一次性启动多进程的方式,</span></span><br><span class="line"><span class="string">        但是由于一些原因,我们不建议使用这种方式,来启动多进程,</span></span><br><span class="line"><span class="string">        而是手动启动多进程,并且还能绑定多个端口</span></span><br><span class="line"><span class="string">    多进程有三个问题:</span></span><br><span class="line"><span class="string">        1. 每个紫禁城都会从父进程中复制出一份IOloop的实例,</span></span><br><span class="line"><span class="string">            如果在创建紫禁城钱,修改了IOloop,会影响到所有的紫禁城实例</span></span><br><span class="line"><span class="string">        2. 所有的进程都是由一个命令启动的,无法做到在不停止服务的情况下修改代码,这样不好</span></span><br><span class="line"><span class="string">        3. 所有进程共享一个端口,想要进行监控,有点难</span></span><br><span class="line"><span class="string">    我自己来启动的话,能在一个进程运行后,修改源代码,来单独在运行一遍,也OK</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">    tornado.ioloop.IOLoop.current().start()</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="第一个程序的批注解释4-0"><a href="#第一个程序的批注解释4-0" class="headerlink" title="第一个程序的批注解释4.0"></a>第一个程序的批注解释4.0</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="keyword">import</span> tornado.ioloop</span><br><span class="line"><span class="keyword">import</span> tornado.httpserver</span><br><span class="line"><span class="keyword">import</span> tornado.options</span><br><span class="line"></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">通常如果程序非正常结束</span></span><br><span class="line"><span class="string">就会出现:&quot;通常每个套接字地址(协议/网络地址/端口)只允许使用一次&quot;</span></span><br><span class="line"><span class="string">这是因为端口没有没释放</span></span><br><span class="line"><span class="string">这时我们的debug模式还没开启</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">tornado为我们提供了一tornado.option模块</span></span><br><span class="line"><span class="string">用于全局参数的定义/存储/转换</span></span><br><span class="line"><span class="string">option:</span></span><br><span class="line"><span class="string">    不让端口写死,让option这个值从外部传进来</span></span><br><span class="line"><span class="string">基础方法与属性:</span></span><br><span class="line"><span class="string">help : 其实就是选项变量的帮助提示信息,一般不用         </span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这个函数的原型</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">def define(</span></span><br><span class="line"><span class="string">    name: str,</span></span><br><span class="line"><span class="string">    default: Any = None,</span></span><br><span class="line"><span class="string">    type: type = None,</span></span><br><span class="line"><span class="string">    help: str = None,</span></span><br><span class="line"><span class="string">    metavar: str = None,</span></span><br><span class="line"><span class="string">    multiple: bool = False,</span></span><br><span class="line"><span class="string">    group: str = None,</span></span><br><span class="line"><span class="string">    callback: Callable[[Any], None] = None,</span></span><br><span class="line"><span class="string">) -&gt; None:</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 这个函数的功能</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">用来定义option选项变量的方法</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 参数</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">name : 选项变量名,必须保证其唯一性,否则会爆出一个option already define 错误</span></span><br><span class="line"><span class="string">default : 设置选项变量的默认值,如果不传,默认为none</span></span><br><span class="line"><span class="string">type : 设置选项变量的类型,比如int,从命令行或者配置文件导入参数时,</span></span><br><span class="line"><span class="string">    tornado会根据输入的数据类型的值进行转换</span></span><br><span class="line"><span class="string">    会根据类型转换成对应的值,转换不成,会报错,那么就有问题了</span></span><br><span class="line"><span class="string">    可以:int float str datetime timedelta</span></span><br><span class="line"><span class="string">    如果没有设置type,会根据default的值进行转换,</span></span><br><span class="line"><span class="string">    如果default没有设置,他就不进行转换</span></span><br><span class="line"><span class="string">multiple : 设置选项变量是否可以为多个值,默认为false    </span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 好我们可以先写一个</span></span><br><span class="line">tornado.options.define(<span class="string">&quot;port&quot;</span>, default=<span class="number">8000</span>, <span class="built_in">type</span>=<span class="built_in">int</span>)</span><br><span class="line"><span class="comment"># 我们要接受一个列表,列表里面的元素的字符串类型,默认给个空</span></span><br><span class="line">tornado.options.define(<span class="string">&quot;list&quot;</span>, default=[], <span class="built_in">type</span>=<span class="built_in">str</span>,multiple=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 然后我们还有一个属性</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">tornado.options.options</span></span><br><span class="line"><span class="string">全局的options对象</span></span><br><span class="line"><span class="string">所有定义的选项变量都会作为改对象的属性</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取参数的方法</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">我们不是把这些参数赋值了么,我们还要把这些参数存储起来</span></span><br><span class="line"><span class="string">tornado.options.parse_command_line()</span></span><br><span class="line"><span class="string">    作用:</span></span><br><span class="line"><span class="string">        转换命令行参数,将命令行参数抓换成为option的属性</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">tornado.web.RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># 转换命令行参数,并保存在tornado.options.options里面</span></span><br><span class="line">    tornado.options.parse_command_line()</span><br><span class="line">    <span class="comment"># 可以打印一下list</span></span><br><span class="line">    print(<span class="string">&#x27;list-&gt;&#x27;</span>,tornado.options.options.<span class="built_in">list</span>)</span><br><span class="line">    app = tornado.web.Application([(<span class="string">r&quot;/&quot;</span>, IndexHandler)])</span><br><span class="line"></span><br><span class="line">    httpServer = tornado.httpserver.HTTPServer(app)</span><br><span class="line">    <span class="comment"># 使用变量的值</span></span><br><span class="line">    httpServer.bind(tornado.options.options.port)</span><br><span class="line"></span><br><span class="line">    httpServer.start(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">    tornado.ioloop.IOLoop.current().start()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 这样我们在启动的时候就能不需要修改代码就能指定端口号了</span></span><br><span class="line">    <span class="comment"># 代码能少改就少改变</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    (venv) D:\PycharmProjects\itcast_tornado&gt;python 01.py --port=9000 --list=good,nice,handsome,cool</span></span><br><span class="line"><span class="string">    list-&gt; [&#x27;good&#x27;, &#x27;nice&#x27;, &#x27;handsome&#x27;, &#x27;cool&#x27;]</span></span><br><span class="line"><span class="string">    [I 191205 17:13:54 web:2246] 200 GET / (127.0.0.1) 1.00ms</span></span><br><span class="line"><span class="string">    [W 191205 17:13:54 web:2246] 404 GET /favicon.ico (127.0.0.1) 1.00ms</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="创建配置文件方式"><a href="#创建配置文件方式" class="headerlink" title="创建配置文件方式"></a>创建配置文件方式</h3><p><code>在linux里面,所有的东西都是文件,就算他是目录,都是文件</code></p><p>创建一个名为config的普通文件,位置在py文件的旁边</p><p>内容如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">port = <span class="number">7000</span></span><br><span class="line"><span class="built_in">list</span> = [<span class="string">&quot;good&quot;</span>,<span class="string">&quot;nice&quot;</span>,<span class="string">&quot;handsome&quot;</span>]</span><br></pre></td></tr></table></figure><p>程序中这样写:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">tornado.options.parse_config_file(<span class="string">&quot;config&quot;</span>)</span><br><span class="line"><span class="comment"># 因为是同级目录,所以相对路径直接写就OK了</span></span><br></pre></td></tr></table></figure><p>然后正常运行程序就OK了</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">D:\PycharmProjects\itcast_tornado\venv\Scripts\python.exe D:/PycharmProjects/itcast_tornado/01.py</span><br><span class="line"><span class="meta">list-&gt;</span><span class="bash"> [<span class="string">&#x27;good&#x27;</span>, <span class="string">&#x27;nice&#x27;</span>, <span class="string">&#x27;handsome&#x27;</span>]</span></span><br><span class="line">[I 191205 17:27:21 web:2246] 200 GET / (127.0.0.1) 0.00ms</span><br><span class="line">[W 191205 17:27:21 web:2246] 404 GET /favicon.ico (127.0.0.1) 0.00ms</span><br></pre></td></tr></table></figure><p>我们现在有两种方式来获得参数,一种是命令行的一种是文件的,但是以后我们要使用哪种方式呢,???  </p><p>都不是…  </p><p>说明:<br>    因为这个配置文件要按照python 的语法要求来进行书写<br>    调用参数的时候,不支持字典类型  </p><p>最终版本:<br>创建一个名为config.py的文件<br>内容如下:  </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 参数 字典类型的了</span></span><br><span class="line"></span><br><span class="line">options = &#123;</span><br><span class="line">    <span class="string">&quot;port&quot;</span>: <span class="number">8080</span>,</span><br><span class="line">    <span class="string">&quot;list&quot;</span>: [<span class="string">&quot;good&quot;</span>, <span class="string">&quot;nice&quot;</span>, <span class="string">&quot;handsome&quot;</span>]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">```    </span><br><span class="line"></span><br><span class="line">脚本这样写:</span><br><span class="line">```python</span><br><span class="line"><span class="keyword">import</span> tornado.web</span><br><span class="line"><span class="keyword">import</span> tornado.ioloop</span><br><span class="line"><span class="keyword">import</span> tornado.httpserver</span><br><span class="line"><span class="keyword">import</span> tornado.options</span><br><span class="line"><span class="keyword">import</span> config</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取参数的方法</span></span><br><span class="line"><span class="comment"># 好我们可以先写一个</span></span><br><span class="line">tornado.options.define(<span class="string">&quot;port&quot;</span>, default=<span class="number">8000</span>, <span class="built_in">type</span>=<span class="built_in">int</span>)</span><br><span class="line"><span class="comment"># 我们要接受一个列表,列表里面的元素的字符串类型,默认给个空</span></span><br><span class="line">tornado.options.define(<span class="string">&quot;list&quot;</span>, default=[], <span class="built_in">type</span>=<span class="built_in">str</span>, multiple=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IndexHandler</span>(<span class="params">tornado.web.RequestHandler</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.write(<span class="string">&quot;main page info tornado!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 可以打印一下list</span></span><br><span class="line">    print(<span class="string">&#x27;list-&gt;&#x27;</span>, config.options[<span class="string">&quot;list&quot;</span>])</span><br><span class="line">    app = tornado.web.Application([(<span class="string">r&quot;/&quot;</span>, IndexHandler)])</span><br><span class="line"></span><br><span class="line">    httpServer = tornado.httpserver.HTTPServer(app)</span><br><span class="line">    <span class="comment"># 使用变量的值</span></span><br><span class="line">    httpServer.bind(config.options[<span class="string">&quot;port&quot;</span>])</span><br><span class="line"></span><br><span class="line">    httpServer.start(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">    tornado.ioloop.IOLoop.current().start()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>这个config可以写成模板,其中可以包含各种配置信息,不仅仅局限于这点儿</p><h3 id="日志"><a href="#日志" class="headerlink" title="日志"></a>日志</h3><p>当我们使用parse_command_line()或者parse_config_file(path)方法时</p><p>tornado会默认开启logging模块功能,向我们的屏幕打印一些相关信息</p><p>如果有处女座不想看这个信息,可以这样</p><p>比如是从普通文件中导入的那种,要在后面再加上一句:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">tornado.options.parse_config_file(<span class="string">&quot;config&quot;</span>)</span><br><span class="line">tornado.options.options.loggings = <span class="literal">None</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> tornado </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python3生成脚本实现重置键盘键位</title>
      <link href="python/collection/python-colemak/"/>
      <url>python/collection/python-colemak/</url>
      
        <content type="html"><![CDATA[<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by 秋叶夏风</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;重置键盘键位&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line">save_format = <span class="string">&quot;bat&quot;</span>  <span class="comment"># 这个值可以修改，有两个选项(bat和reg)，可选择生成bat批处理文件或者reg注册表脚本文件,功能一样</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CountError</span>(<span class="params">Exception</span>):</span>  <span class="comment"># 文本文件格式错误异常</span></span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">FileFormatError</span>(<span class="params">Exception</span>):</span>  <span class="comment"># save_format值异常</span></span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> save_format <span class="keyword">not</span> <span class="keyword">in</span> [<span class="string">&quot;bat&quot;</span>, <span class="string">&quot;reg&quot;</span>]:</span><br><span class="line">    <span class="keyword">raise</span> FileFormatError(<span class="string">&quot;The variable &#x27;save_format&#x27;`s value must be &#x27;bat&#x27; or &#x27;reg&#x27;.&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> os.path.isdir(<span class="string">&quot;layout_&quot;</span> + save_format):</span><br><span class="line">        os.mkdir(<span class="string">&quot;layout_&quot;</span> + save_format)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(sys.argv) == <span class="number">1</span>:</span><br><span class="line">        <span class="keyword">if</span> save_format == <span class="string">&quot;bat&quot;</span>:</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;layout_bat/recover.bat&quot;</span>, <span class="string">&#x27;w&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">                f.write(</span><br><span class="line">                    <span class="string">&#x27;@echo off\nreg delete &quot;hklm\\system\\currentcontrolset\\control\\keyboard layout&quot; /v &quot;ScanCode Map&quot; /f\necho &quot;键位已恢复，重启系统后生效&quot;\npause&#x27;</span>)</span><br><span class="line">            <span class="built_in">input</span>(<span class="string">&quot;恢复文件recover.bat已生成至layout_bat文件夹下，以管理员身份右键执行该文件后重启系统生效。\n按回车键退出程序...&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;layout_reg/recover.reg&quot;</span>, <span class="string">&#x27;w&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">                f.write(</span><br><span class="line">                    <span class="string">&#x27;Windows Registry Editor Version 5.00\n[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout]\n&quot;ScanCode Map&quot;=hex:00,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00&#x27;</span>)</span><br><span class="line">            <span class="built_in">input</span>(<span class="string">&quot;恢复文件recover.reg已生成至layout_reg文件夹下，双击执行该文件后重启系统生效。\n按回车键退出程序...&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">elif</span> <span class="built_in">len</span>(sys.argv) == <span class="number">2</span>:</span><br><span class="line">        scan_code_dict = &#123;</span><br><span class="line">            <span class="string">&quot;00 00&quot;</span>: <span class="string">&quot;None&quot;</span>,</span><br><span class="line">            <span class="string">&quot;01 00&quot;</span>: <span class="string">&quot;Esc&quot;</span>,  <span class="comment"># 即Esc键的扫描码是&quot;0001&quot;</span></span><br><span class="line">            <span class="string">&quot;02 00&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">            <span class="string">&quot;03 00&quot;</span>: <span class="string">&quot;2&quot;</span>,</span><br><span class="line">            <span class="string">&quot;04 00&quot;</span>: <span class="string">&quot;3&quot;</span>,</span><br><span class="line">            <span class="string">&quot;05 00&quot;</span>: <span class="string">&quot;4&quot;</span>,</span><br><span class="line">            <span class="string">&quot;06 00&quot;</span>: <span class="string">&quot;5&quot;</span>,</span><br><span class="line">            <span class="string">&quot;07 00&quot;</span>: <span class="string">&quot;6&quot;</span>,</span><br><span class="line">            <span class="string">&quot;08 00&quot;</span>: <span class="string">&quot;7&quot;</span>,</span><br><span class="line">            <span class="string">&quot;09 00&quot;</span>: <span class="string">&quot;8&quot;</span>,</span><br><span class="line">            <span class="string">&quot;0a 00&quot;</span>: <span class="string">&quot;9&quot;</span>,</span><br><span class="line">            <span class="string">&quot;0b 00&quot;</span>: <span class="string">&quot;0&quot;</span>,</span><br><span class="line">            <span class="string">&quot;0c 00&quot;</span>: <span class="string">&quot;-&quot;</span>,</span><br><span class="line">            <span class="string">&quot;0d 00&quot;</span>: <span class="string">&quot;=&quot;</span>,</span><br><span class="line">            <span class="string">&quot;0e 00&quot;</span>: <span class="string">&quot;Backspace&quot;</span>,</span><br><span class="line">            <span class="string">&quot;0f 00&quot;</span>: <span class="string">&quot;Tab&quot;</span>,</span><br><span class="line">            <span class="string">&quot;10 00&quot;</span>: <span class="string">&quot;Q&quot;</span>,</span><br><span class="line">            <span class="string">&quot;11 00&quot;</span>: <span class="string">&quot;W&quot;</span>,</span><br><span class="line">            <span class="string">&quot;12 00&quot;</span>: <span class="string">&quot;E&quot;</span>,</span><br><span class="line">            <span class="string">&quot;13 00&quot;</span>: <span class="string">&quot;R&quot;</span>,</span><br><span class="line">            <span class="string">&quot;14 00&quot;</span>: <span class="string">&quot;T&quot;</span>,</span><br><span class="line">            <span class="string">&quot;15 00&quot;</span>: <span class="string">&quot;Y&quot;</span>,</span><br><span class="line">            <span class="string">&quot;16 00&quot;</span>: <span class="string">&quot;U&quot;</span>,</span><br><span class="line">            <span class="string">&quot;17 00&quot;</span>: <span class="string">&quot;I&quot;</span>,</span><br><span class="line">            <span class="string">&quot;18 00&quot;</span>: <span class="string">&quot;O&quot;</span>,</span><br><span class="line">            <span class="string">&quot;19 00&quot;</span>: <span class="string">&quot;P&quot;</span>,</span><br><span class="line">            <span class="string">&quot;1a 00&quot;</span>: <span class="string">&quot;[&quot;</span>,</span><br><span class="line">            <span class="string">&quot;1b 00&quot;</span>: <span class="string">&quot;]&quot;</span>,</span><br><span class="line">            <span class="string">&quot;1c 00&quot;</span>: <span class="string">&quot;Enter&quot;</span>,</span><br><span class="line">            <span class="string">&quot;1d 00&quot;</span>: <span class="string">&quot;Left Ctrl&quot;</span>,</span><br><span class="line">            <span class="string">&quot;1e 00&quot;</span>: <span class="string">&quot;A&quot;</span>,</span><br><span class="line">            <span class="string">&quot;1f 00&quot;</span>: <span class="string">&quot;S&quot;</span>,</span><br><span class="line">            <span class="string">&quot;20 00&quot;</span>: <span class="string">&quot;D&quot;</span>,</span><br><span class="line">            <span class="string">&quot;21 00&quot;</span>: <span class="string">&quot;F&quot;</span>,</span><br><span class="line">            <span class="string">&quot;22 00&quot;</span>: <span class="string">&quot;G&quot;</span>,</span><br><span class="line">            <span class="string">&quot;23 00&quot;</span>: <span class="string">&quot;H&quot;</span>,</span><br><span class="line">            <span class="string">&quot;24 00&quot;</span>: <span class="string">&quot;J&quot;</span>,</span><br><span class="line">            <span class="string">&quot;25 00&quot;</span>: <span class="string">&quot;K&quot;</span>,</span><br><span class="line">            <span class="string">&quot;26 00&quot;</span>: <span class="string">&quot;L&quot;</span>,</span><br><span class="line">            <span class="string">&quot;27 00&quot;</span>: <span class="string">&quot;Semicolon&quot;</span>,  <span class="comment"># 由评论区指出，键盘上的“;”应该用其他值代替，否则会与配置文本文件中的“;”混淆</span></span><br><span class="line">            <span class="string">&quot;28 00&quot;</span>: <span class="string">&quot;&#x27;&quot;</span>,</span><br><span class="line">            <span class="string">&quot;29 00&quot;</span>: <span class="string">&quot;`&quot;</span>,</span><br><span class="line">            <span class="string">&quot;2a 00&quot;</span>: <span class="string">&quot;Left Shift&quot;</span>,</span><br><span class="line">            <span class="string">&quot;2b 00&quot;</span>: <span class="string">&quot;\\&quot;</span>,</span><br><span class="line">            <span class="string">&quot;2c 00&quot;</span>: <span class="string">&quot;Z&quot;</span>,</span><br><span class="line">            <span class="string">&quot;2d 00&quot;</span>: <span class="string">&quot;X&quot;</span>,</span><br><span class="line">            <span class="string">&quot;2e 00&quot;</span>: <span class="string">&quot;C&quot;</span>,</span><br><span class="line">            <span class="string">&quot;2f 00&quot;</span>: <span class="string">&quot;V&quot;</span>,</span><br><span class="line">            <span class="string">&quot;30 00&quot;</span>: <span class="string">&quot;B&quot;</span>,</span><br><span class="line">            <span class="string">&quot;31 00&quot;</span>: <span class="string">&quot;N&quot;</span>,</span><br><span class="line">            <span class="string">&quot;32 00&quot;</span>: <span class="string">&quot;M&quot;</span>,</span><br><span class="line">            <span class="string">&quot;33 00&quot;</span>: <span class="string">&quot;,&quot;</span>,</span><br><span class="line">            <span class="string">&quot;34 00&quot;</span>: <span class="string">&quot;.&quot;</span>,</span><br><span class="line">            <span class="string">&quot;35 00&quot;</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">            <span class="string">&quot;36 00&quot;</span>: <span class="string">&quot;Right Shift&quot;</span>,</span><br><span class="line">            <span class="string">&quot;37 00&quot;</span>: <span class="string">&quot;n*&quot;</span>,</span><br><span class="line">            <span class="string">&quot;38 00&quot;</span>: <span class="string">&quot;Left Alt&quot;</span>,</span><br><span class="line">            <span class="string">&quot;39 00&quot;</span>: <span class="string">&quot;Space&quot;</span>,</span><br><span class="line">            <span class="string">&quot;3a 00&quot;</span>: <span class="string">&quot;Caps Lock&quot;</span>,</span><br><span class="line">            <span class="string">&quot;3b 00&quot;</span>: <span class="string">&quot;F1&quot;</span>,</span><br><span class="line">            <span class="string">&quot;3c 00&quot;</span>: <span class="string">&quot;F2&quot;</span>,</span><br><span class="line">            <span class="string">&quot;3d 00&quot;</span>: <span class="string">&quot;F3&quot;</span>,</span><br><span class="line">            <span class="string">&quot;3e 00&quot;</span>: <span class="string">&quot;F4&quot;</span>,</span><br><span class="line">            <span class="string">&quot;3f 00&quot;</span>: <span class="string">&quot;F5&quot;</span>,</span><br><span class="line">            <span class="string">&quot;40 00&quot;</span>: <span class="string">&quot;F6&quot;</span>,</span><br><span class="line">            <span class="string">&quot;41 00&quot;</span>: <span class="string">&quot;F7&quot;</span>,</span><br><span class="line">            <span class="string">&quot;42 00&quot;</span>: <span class="string">&quot;F8&quot;</span>,</span><br><span class="line">            <span class="string">&quot;43 00&quot;</span>: <span class="string">&quot;F9&quot;</span>,</span><br><span class="line">            <span class="string">&quot;44 00&quot;</span>: <span class="string">&quot;F10&quot;</span>,</span><br><span class="line">            <span class="string">&quot;45 00&quot;</span>: <span class="string">&quot;Num Lock&quot;</span>,</span><br><span class="line">            <span class="string">&quot;46 00&quot;</span>: <span class="string">&quot;Scroll Lock&quot;</span>,</span><br><span class="line">            <span class="string">&quot;47 00&quot;</span>: <span class="string">&quot;n7&quot;</span>,</span><br><span class="line">            <span class="string">&quot;48 00&quot;</span>: <span class="string">&quot;n8&quot;</span>,</span><br><span class="line">            <span class="string">&quot;49 00&quot;</span>: <span class="string">&quot;n9&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4a 00&quot;</span>: <span class="string">&quot;n-&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4b 00&quot;</span>: <span class="string">&quot;n4&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4c 00&quot;</span>: <span class="string">&quot;n5&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4d 00&quot;</span>: <span class="string">&quot;n6&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4e 00&quot;</span>: <span class="string">&quot;n+&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4f 00&quot;</span>: <span class="string">&quot;n1&quot;</span>,</span><br><span class="line">            <span class="string">&quot;50 00&quot;</span>: <span class="string">&quot;n2&quot;</span>,</span><br><span class="line">            <span class="string">&quot;51 00&quot;</span>: <span class="string">&quot;n3&quot;</span>,</span><br><span class="line">            <span class="string">&quot;52 00&quot;</span>: <span class="string">&quot;n0&quot;</span>,</span><br><span class="line">            <span class="string">&quot;53 00&quot;</span>: <span class="string">&quot;n.&quot;</span>,</span><br><span class="line">            <span class="string">&quot;57 00&quot;</span>: <span class="string">&quot;F11&quot;</span>,</span><br><span class="line">            <span class="string">&quot;58 00&quot;</span>: <span class="string">&quot;F12&quot;</span>,</span><br><span class="line"></span><br><span class="line">            <span class="string">&quot;1c e0&quot;</span>: <span class="string">&quot;nEnter&quot;</span>,</span><br><span class="line">            <span class="string">&quot;1d e0&quot;</span>: <span class="string">&quot;Right Ctrl&quot;</span>,</span><br><span class="line">            <span class="string">&quot;37 e0&quot;</span>: <span class="string">&quot;PrtSc&quot;</span>,</span><br><span class="line">            <span class="string">&quot;38 e0&quot;</span>: <span class="string">&quot;Right Alt&quot;</span>,</span><br><span class="line">            <span class="string">&quot;47 e0&quot;</span>: <span class="string">&quot;Home&quot;</span>,</span><br><span class="line">            <span class="string">&quot;48 e0&quot;</span>: <span class="string">&quot;Up&quot;</span>,</span><br><span class="line">            <span class="string">&quot;49 e0&quot;</span>: <span class="string">&quot;Page Up&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4b e0&quot;</span>: <span class="string">&quot;Left&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4d e0&quot;</span>: <span class="string">&quot;Right&quot;</span>,</span><br><span class="line">            <span class="string">&quot;4f e0&quot;</span>: <span class="string">&quot;End&quot;</span>,</span><br><span class="line">            <span class="string">&quot;50 e0&quot;</span>: <span class="string">&quot;Down&quot;</span>,</span><br><span class="line">            <span class="string">&quot;51 e0&quot;</span>: <span class="string">&quot;Page Down&quot;</span>,</span><br><span class="line">            <span class="string">&quot;52 e0&quot;</span>: <span class="string">&quot;Insert&quot;</span>,</span><br><span class="line">            <span class="string">&quot;53 e0&quot;</span>: <span class="string">&quot;Delete&quot;</span>,</span><br><span class="line">            <span class="string">&quot;5b e0&quot;</span>: <span class="string">&quot;Left Windows&quot;</span>,</span><br><span class="line">            <span class="string">&quot;5c e0&quot;</span>: <span class="string">&quot;Right Windows&quot;</span>,</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        fun_key_dict = <span class="built_in">dict</span>((m.upper(), n) <span class="keyword">for</span> n, m <span class="keyword">in</span> scan_code_dict.items())  <span class="comment"># 键值互换,键值全大写</span></span><br><span class="line">        content = <span class="string">&#x27;00 00 00 00 00 00 00 00&#x27;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 用于暂时保存映射前后的键位，判断这次键位修改是否有风险</span></span><br><span class="line">        before_map_set = <span class="built_in">set</span>()</span><br><span class="line">        after_map_set = <span class="built_in">set</span>()</span><br><span class="line"></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(sys.argv[<span class="number">1</span>]) <span class="keyword">as</span> f:</span><br><span class="line">            p = f.read().strip().split(<span class="string">&#x27;;&#x27;</span>)</span><br><span class="line">            p.remove(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">            content += <span class="string">&#x27; &#123;:0&gt;2x&#125; 00 00 00&#x27;</span>.<span class="built_in">format</span>(<span class="built_in">len</span>(p) + <span class="number">1</span>)</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                <span class="keyword">for</span> i <span class="keyword">in</span> p:</span><br><span class="line">                    <span class="keyword">if</span> <span class="built_in">len</span>(i.strip().split(<span class="string">&#x27;:&#x27;</span>)) == <span class="number">2</span>:</span><br><span class="line">                        before_map_set.add(i.split(<span class="string">&#x27;:&#x27;</span>)[<span class="number">0</span>].strip().upper())</span><br><span class="line">                        after_map_set.add(i.split(<span class="string">&#x27;:&#x27;</span>)[<span class="number">1</span>].strip().upper())</span><br><span class="line">                        content += <span class="string">&#x27; &#x27;</span> + fun_key_dict[i.split(<span class="string">&#x27;:&#x27;</span>)[<span class="number">1</span>].strip().upper()] + <span class="string">&#x27; &#x27;</span> + fun_key_dict[</span><br><span class="line">                            i.split(<span class="string">&#x27;:&#x27;</span>)[<span class="number">0</span>].strip().upper()]</span><br><span class="line">                    <span class="keyword">else</span>:</span><br><span class="line">                        <span class="keyword">raise</span> CountError</span><br><span class="line">                content += <span class="string">&#x27; 00 00 00 00&#x27;</span></span><br><span class="line">            <span class="keyword">except</span> KeyError:</span><br><span class="line">                print(<span class="string">&quot;文件中键名称有误&quot;</span>)</span><br><span class="line"></span><br><span class="line">            <span class="keyword">except</span> CountError:</span><br><span class="line">                print(<span class="string">&quot;文件中未按格式书写&quot;</span>)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="keyword">if</span> before_map_set != after_map_set:</span><br><span class="line">                    run = <span class="built_in">input</span>(<span class="string">&quot;此次键位替换存在风险，&#123;&#125;键功能将在键盘上无对应按键，是否继续？(输入y继续，否则退出程序)&quot;</span>.<span class="built_in">format</span>(</span><br><span class="line">                        <span class="built_in">str</span>(before_map_set - after_map_set)[<span class="number">1</span>:-<span class="number">1</span>]))</span><br><span class="line">                    <span class="keyword">if</span> run != <span class="string">&#x27;y&#x27;</span>:</span><br><span class="line">                        sys.exit()</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> save_format == <span class="string">&quot;bat&quot;</span>:</span><br><span class="line">                    <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;layout_bat/&quot;</span> + <span class="string">&#x27;.&#x27;</span>.join(sys.argv[<span class="number">1</span>].split(<span class="string">&#x27;\\&#x27;</span>)[-<span class="number">1</span>].split(<span class="string">&#x27;.&#x27;</span>)[:-<span class="number">1</span>]) + <span class="string">&#x27;.bat&#x27;</span>, <span class="string">&#x27;w&#x27;</span>) <span class="keyword">as</span> g:</span><br><span class="line">                        g.write(</span><br><span class="line">                            <span class="string">&#x27;@echo off\nreg add &quot;hklm\\system\\currentcontrolset\\control\\keyboard layout&quot; /v &quot;ScanCode Map&quot; /t REG_BINARY /d &quot;&#123;&#125;&quot; /f\necho &quot;键位已完成修改，重启系统后生效&quot;\npause&#x27;</span>.<span class="built_in">format</span>(</span><br><span class="line">                                <span class="string">&#x27;&#x27;</span>.join(content.split())))</span><br><span class="line">                    <span class="built_in">input</span>(<span class="string">&quot;...\n&#123;&#125;文件已生成至layout_bat目录下，右键以管理员身份执行该文件后重启系统生效。\n按回车键退出程序...&quot;</span>.<span class="built_in">format</span>(</span><br><span class="line">                        <span class="string">&#x27;.&#x27;</span>.join(sys.argv[<span class="number">1</span>].split(<span class="string">&#x27;\\&#x27;</span>)[-<span class="number">1</span>].split(<span class="string">&#x27;.&#x27;</span>)[:-<span class="number">1</span>]) + <span class="string">&#x27;.&#x27;</span> + save_format))</span><br><span class="line"></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;layout_reg/&quot;</span> + <span class="string">&#x27;.&#x27;</span>.join(sys.argv[<span class="number">1</span>].split(<span class="string">&#x27;\\&#x27;</span>)[-<span class="number">1</span>].split(<span class="string">&#x27;.&#x27;</span>)[:-<span class="number">1</span>]) + <span class="string">&#x27;.reg&#x27;</span>, <span class="string">&#x27;w&#x27;</span>) <span class="keyword">as</span> g:</span><br><span class="line">                        g.write(</span><br><span class="line">                            <span class="string">&#x27;Windows Registry Editor Version 5.00\n[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout]\n&quot;ScanCode Map&quot;=hex:&#123;&#125;&#x27;</span>.<span class="built_in">format</span>(</span><br><span class="line">                                <span class="string">&#x27;,&#x27;</span>.join(content.split())))</span><br><span class="line"></span><br><span class="line">                    <span class="built_in">input</span>(<span class="string">&quot;...\n&#123;&#125;文件已生成至layout_reg目录下，双击执行该文件后重启系统生效。\n按回车键退出程序...&quot;</span>.<span class="built_in">format</span>(</span><br><span class="line">                        <span class="string">&#x27;.&#x27;</span>.join(sys.argv[<span class="number">1</span>].split(<span class="string">&#x27;\\&#x27;</span>)[-<span class="number">1</span>].split(<span class="string">&#x27;.&#x27;</span>)[:-<span class="number">1</span>]) + <span class="string">&#x27;.&#x27;</span> + save_format))</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="built_in">input</span>(<span class="string">&quot;传入参数错误，按回车键退出程序...&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>Typing by 自然码+colemak</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">重叠: </span><br><span class="line">gg 更</span><br><span class="line">ll 来</span><br><span class="line">uu 数</span><br><span class="line">yy 应</span><br><span class="line">rr 软</span><br><span class="line">ss 送</span><br><span class="line">hh 行</span><br><span class="line">nn 您</span><br><span class="line">ii 吃</span><br><span class="line">zz 贼</span><br><span class="line">xx 写</span><br><span class="line">vv 追</span><br><span class="line">kk 考</span><br><span class="line">mm 面</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django笔记</title>
      <link href="python/Django/django-blog/"/>
      <url>python/Django/django-blog/</url>
      
        <content type="html"><![CDATA[<h1 id="多人博客项目"><a href="#多人博客项目" class="headerlink" title="多人博客项目"></a>多人博客项目</h1><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p>DjangoMVC架构设计的开源的web快速开发框架</p><h2 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h2><ul><li>能够快速开发,如Auth,Cache,模板</li><li>MVC设计模式<ul><li>实用的后台管理</li><li>自带ORM,Template,Form,Auth核心</li></ul></li><li>组件<ul><li>简洁的URL设计</li><li>周边插件丰富<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h2></li></ul></li><li>重,因为东西大而全</li><li>同步阻塞</li></ul><p>所以Django的设计目标就是一款大而全,<br>便于企业快速开发项目,因此应用比较广</p><h2 id="模板"><a href="#模板" class="headerlink" title="模板"></a>模板</h2><p>如果使用react实现前端页面,其实Django就没有必须使用模板,它其实就是一个后台服务程序,接收请求,响应数据。接口设计就可以是纯粹的Restful风格。</p><p>模板的目的就是为了可视化| ,将数据按照一定布局格式输出,而不是为了数据处理,所以一般不会有复杂的处理逻辑。模板的引入实现了业务逻辑和显示格式的分离,这样,在开发中,就可以分工协作,页面开发完成页面布局设计,后台开发完成数据处理逻辑的实现。</p><p>Python的模板引|擎默认使用Django template language (DTL)构建</p><h2 id="模板配置"><a href="#模板配置" class="headerlink" title="模板配置"></a>模板配置</h2>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django模板（过滤器）</title>
      <link href="python/Django/django-filder/"/>
      <url>python/Django/django-filder/</url>
      
        <content type="html"><![CDATA[<p>本文转自:<a href="https://www.cnblogs.com/qingtianyu2015/p/6064073.html">https://www.cnblogs.com/qingtianyu2015/p/6064073.html</a></p><h3 id="1、add"><a href="#1、add" class="headerlink" title="1、add"></a>1、add</h3><p>使用形式为：{ {   value | add: “2” } }<br>意义：将value的值增加2  </p><h3 id="2、addslashes"><a href="#2、addslashes" class="headerlink" title="2、addslashes"></a>2、addslashes</h3><p>使用形式为：{ {   value | addslashes  } }<br>意义：在value中的引号前增加反斜线  </p><h3 id="3、capfirst"><a href="#3、capfirst" class="headerlink" title="3、capfirst"></a>3、capfirst</h3><p>使用形式为：{ {   value | capfirst  } }<br>意义：value的第一个字符转化成大写形式  </p><h3 id="4、cut"><a href="#4、cut" class="headerlink" title="4、cut"></a>4、cut</h3><p>使用形式为：{ {   value | cut:arg } }， 例如，如果value是“String with spaces” arg是” “那么输出是”Stringwithspaces”<br>意义：从给定value中删除所有arg的值  </p><h3 id="5、date"><a href="#5、date" class="headerlink" title="5、date"></a>5、date</h3><p>使用形式为：：<br>(a) { {   value | date:”D d M Y”  } }，例如，如果value是一个datetime对象(datetime.datetime.now())那么输出将是字符串”Wed 09 Jan 2008”<br>(b) { {   value | date  } }，这种形式没有格式化字符串，这时候，格式化字符串会自动采用DATE_FORMAT所设置的形式。<br>意义：将日期格式数据按照给定的格式输出  </p><h3 id="6、default"><a href="#6、default" class="headerlink" title="6、default"></a>6、default</h3><p>使用形式：{ {   value | default: “nothing”  } }，例如，如果value是“”，那么输出将是nothing<br>意义：如果value的意义是False，那么输出使用缺省值  </p><h3 id="7、default-if-none"><a href="#7、default-if-none" class="headerlink" title="7、default_if_none"></a>7、default_if_none</h3><p>使用形式：{ {   value | default_if_none:”nothing”  } }，例如，如果value是None，那么输出将是nothing<br>意义：如果value是None，那么输出将使用缺省值  </p><h3 id="8、dictsort"><a href="#8、dictsort" class="headerlink" title="8、dictsort"></a>8、dictsort</h3><p>意义：如果value的值是一个字典，那么返回值是按照关键字排序的结果<br>使用形式：{ {   value | dictsort:”name” } }，例如，<br>如果value是：<br>[<br>{‘name’: ‘zed’, ‘age’: 19},<br>{‘name’: ‘amy’, ‘age’: 22},<br>{‘name’: ‘joe’, ‘age’: 31}, ]<br>那么，输出是：<br>[<br>{‘name’: ‘amy’, ‘age’: 22},<br>{‘name’: ‘joe’, ‘age’: 31},<br>{‘name’: ‘zed’, ‘age’: 19}, ]  </p><h3 id="9、dictsortreversed"><a href="#9、dictsortreversed" class="headerlink" title="9、dictsortreversed"></a>9、dictsortreversed</h3><p>意义：如果value的值是一个字典，那么返回值是按照关键字排序的结果的反序<br>使用形式：与上述(8)完全相同。  </p><h3 id="10、divisibleby"><a href="#10、divisibleby" class="headerlink" title="10、divisibleby"></a>10、divisibleby</h3><p>使用形式：{ {   value | divisibleby:arg } }，如果value是21，arg是3，那么输出将是True<br>意义：如果value能够被arg整除，那么返回值将是True  </p><h3 id="11、escape"><a href="#11、escape" class="headerlink" title="11、escape"></a>11、escape</h3><p>使用形式：{ {   value | escape } }<br>意义：替换value中的某些字符，以适应HTML格式，包括：<br>&lt; is converted to &lt;  </p><blockquote><p>is converted to &gt;<br>‘ (single quote) is converted to &#39;<br>“ (double quote) is converted to &quot;<br>&amp; is converted to &amp;  </p></blockquote><p>注：escape仅仅在输出的时候才起作用，所以escape不能够用在链式过滤器的中间，<br>他应该总是最后一个过滤器，如果想在链式过滤器的中间使用，那么可以使用force_escape  </p><h3 id="12、escapejs"><a href="#12、escapejs" class="headerlink" title="12、escapejs"></a>12、escapejs</h3><p>使用形式：{ {   value | escapejs  } }<br>意义：替换value中的某些字符，以适应JAVASCRIPT和JSON格式。  </p><h3 id="13、filesizeformat"><a href="#13、filesizeformat" class="headerlink" title="13、filesizeformat"></a>13、filesizeformat</h3><p>使用形式：{ {   value | filesizeformat  } }<br>意义：格式化value，使其成为易读的文件大小，例如：13KB，4.1MB等。  </p><h3 id="14、first"><a href="#14、first" class="headerlink" title="14、first"></a>14、first</h3><p>使用形式：{ {   value | first  } }<br>意义：返回列表中的第一个Item，例如，如果value是列表[‘a’,’b’,’c’]，那么输出将是’a’。  </p><h3 id="15、floatformat"><a href="#15、floatformat" class="headerlink" title="15、floatformat"></a>15、floatformat</h3><p>使用形式：{ {   value | floatformat } }或者{ {  value|floatformat:arg } }， arg可以是正数也可以是负数。没有参数的floatformat相当于floatformat:-1  </p><h4 id="1、如果不带arg，那么引擎会四舍五入，同时最多只保留一位小数。"><a href="#1、如果不带arg，那么引擎会四舍五入，同时最多只保留一位小数。" class="headerlink" title="1、如果不带arg，那么引擎会四舍五入，同时最多只保留一位小数。"></a>1、如果不带arg，那么引擎会四舍五入，同时最多只保留一位小数。</h4><p>34.23234{ {   value|floatformat  } }34.234.00000{ {   value|floatformat  } }3434.26000{ {   value|floatformat  } }34.3  </p><h4 id="2、如果arg是正数，那么引擎会四舍五入，同时保留arg位的小数。"><a href="#2、如果arg是正数，那么引擎会四舍五入，同时保留arg位的小数。" class="headerlink" title="2、如果arg是正数，那么引擎会四舍五入，同时保留arg位的小数。"></a>2、如果arg是正数，那么引擎会四舍五入，同时保留arg位的小数。</h4><p>34.23234{ {   value|floatformat:3  } }34.23234.00000{ {   value|floatformat:3  } }34.00034.26000{ {   value|floatformat:3  } }34.260  </p><h4 id="3、如果arg是负数，那么引擎会四舍五入，如果有小数部分，那么保留arg位小数；否则，则没有任何小数部分。"><a href="#3、如果arg是负数，那么引擎会四舍五入，如果有小数部分，那么保留arg位小数；否则，则没有任何小数部分。" class="headerlink" title="3、如果arg是负数，那么引擎会四舍五入，如果有小数部分，那么保留arg位小数；否则，则没有任何小数部分。"></a>3、如果arg是负数，那么引擎会四舍五入，如果有小数部分，那么保留arg位小数；否则，则没有任何小数部分。</h4><p>34.23234{ {   value|floatformat:”-3”  } }34.23234.00000{ {   value|floatformat:”-3”  } }3434.26000{ {   value|floatformat:”-3”  } }34.26(16)get_digit  </p><p>使用形式：{ {   value | get_digit:”arg” } }，例如，如果value是123456789，arg是2，那么输出是8<br>意义：给定一个数字，返回，请求的数字，记住：1代表最右边的数字，如果value不是合法输入，那么会返回所有原有值。  </p><h3 id="16、iriencode"><a href="#16、iriencode" class="headerlink" title="16、iriencode"></a>16、iriencode</h3><p>使用形式：{ {  value | iriencode } }<br>意义：如果value中有非ASCII字符，那么将其进行抓化成URL中适合的编码，如果value已经进行过URLENCODE，<br>改操作就不会再起作用。  </p><h3 id="17、join"><a href="#17、join" class="headerlink" title="17、join"></a>17、join</h3><p>使用形式：{ {   value | join:”arg” } }，如果value是[‘a’,’b’,’c’]，arg是’//‘那么输出是a//b//c<br>意义：使用指定的字符串连接一个list，作用如同python的str.join(list)  </p><h3 id="18、last"><a href="#18、last" class="headerlink" title="18、last"></a>18、last</h3><p>使用形式：{ {   value | last  } }<br>意义：返回列表中的最后一个Item  </p><h3 id="19、length"><a href="#19、length" class="headerlink" title="19、length"></a>19、length</h3><p>使用形式：{ {   value | length  } }<br>意义：返回value的长度。  </p><h3 id="20、length-is"><a href="#20、length-is" class="headerlink" title="20、length_is"></a>20、length_is</h3><p>使用形式：{ {   value | length_is:”arg” } }<br>意义：返回True，如果value的长度等于arg的时候，例如：如果value是[‘a’,’b’,’c’]，arg是3，那么返回True  </p><h3 id="21、linebreaks"><a href="#21、linebreaks" class="headerlink" title="21、linebreaks"></a>21、linebreaks</h3><p>使用形式：{ {  value|linebreaks } }<br>意义：value中的”\n”将被<br/>替代，并且整个value使用</p>包围起来，从而适和HTML的格式  </p><h3 id="22、linebreaksbr"><a href="#22、linebreaksbr" class="headerlink" title="22、linebreaksbr"></a>22、linebreaksbr</h3><p>使用形式：{ {  value |linebreaksbr } }<br>意义：value中的”\n”将被<br/>替代  </p><h3 id="23、linenumbers"><a href="#23、linenumbers" class="headerlink" title="23、linenumbers"></a>23、linenumbers</h3><p>使用形式：{ {  value | linenumbers } }<br>意义：显示的文本，带有行数。  </p><h3 id="24、ljust"><a href="#24、ljust" class="headerlink" title="24、ljust"></a>24、ljust</h3><p>使用形式：{ {  value | ljust } }<br>意义：在一个给定宽度的字段中，左对齐显示value  </p><h3 id="25、center"><a href="#25、center" class="headerlink" title="25、center"></a>25、center</h3><p>使用形式：{ {  value | center } }<br>意义：在一个给定宽度的字段中，中心对齐显示value  </p><h3 id="26、rjust"><a href="#26、rjust" class="headerlink" title="26、rjust"></a>26、rjust</h3><p>使用形式：{ {  value | rjust } }<br>意义：在一个给定宽度的字段中，右对齐显示value  </p><h3 id="27、lower"><a href="#27、lower" class="headerlink" title="27、lower"></a>27、lower</h3><p>使用形式：{ {  value | lower } }<br>意义：将一个字符串转换成小写形式  </p><h3 id="28、make-list"><a href="#28、make-list" class="headerlink" title="28、make_list"></a>28、make_list</h3><p>使用形式：{ {  value | make_list } }<br>意义：将value转换成一个list，对于字符串，转换成字符list；对于整数，转换成整数list<br>例如value是Joel，那么输出将是[u’J’,u’o’,u’e’,u’l’]；value是123，那么输出将是[1,2,3]  </p><h3 id="29、pluralize"><a href="#29、pluralize" class="headerlink" title="29、pluralize"></a>29、pluralize</h3><p>使用形式：{ {  value | pluralize } }，或者{ {  value | pluralize:”es” } }，或者{ {  value | pluralize:”y,ies” } }<br>意义：如果value不是1，则返回一个复数后缀，缺省的后缀是’s’  </p><h3 id="30、random"><a href="#30、random" class="headerlink" title="30、random"></a>30、random</h3><p>使用形式：{ {  value | random } }<br>意义：从给定的list中返回一个任意的Item  </p><h3 id="31、removetags"><a href="#31、removetags" class="headerlink" title="31、removetags"></a>31、removetags</h3><p>使用形式：{ {  value | removetags:”tag1 tag2 tag3…” } }<br>意义：删除value中tag1,tag2….的标签。例如，如果value是<b>Joel</b> <button>is</button> a <span>slug</span><br>tags是”b span”，那么输出将是：Joel <button>is</button> a slug  </p><h3 id="32、safe"><a href="#32、safe" class="headerlink" title="32、safe"></a>32、safe</h3><p>使用形式：{ {  value | safe } }<br>意义：当系统设置autoescaping打开的时候，该过滤器使得输出不进行escape转换  </p><h3 id="33、safeseq"><a href="#33、safeseq" class="headerlink" title="33、safeseq"></a>33、safeseq</h3><p>与上述safe基本相同，但有一点不同的就是：safe是针对字符串，而safeseq是针对多个字符串组成的sequence  </p><h3 id="34、slice"><a href="#34、slice" class="headerlink" title="34、slice"></a>34、slice</h3><p>使用形式：{ {  some_list | slice:”:2” } }<br>意义：与python语法中的slice相同，:2表示第一的第二个元素  </p><h3 id="35、slugify"><a href="#35、slugify" class="headerlink" title="35、slugify"></a>35、slugify</h3><p>使用形式：{ {  value | slugify } }<br>意义：将value转换成小写形式，同事删除所有分单词字符，并将空格变成横线<br>例如：如果value是Joel is a slug，那么输出将是joel-is-a-slug  </p><h3 id="36、stringformat"><a href="#36、stringformat" class="headerlink" title="36、stringformat"></a>36、stringformat</h3><p>这个不经常用，先不说  </p><h3 id="37、striptags"><a href="#37、striptags" class="headerlink" title="37、striptags"></a>37、striptags</h3><p>使用形式：{ {  value | striptags } }<br>意义：删除value中的所有HTML标签  </p><h3 id="38、time"><a href="#38、time" class="headerlink" title="38、time"></a>38、time</h3><p>使用形式：{ {  value | time:”H:i” } }或者{ {  value | time } }<br>意义：格式化时间输出，如果time后面没有格式化参数，那么输出按照TIME_FORMAT中设置的进行。  </p><h3 id="39、title"><a href="#39、title" class="headerlink" title="39、title"></a>39、title</h3><p>转换一个字符串成为title格式。  </p><h3 id="40、truncatewords"><a href="#40、truncatewords" class="headerlink" title="40、truncatewords"></a>40、truncatewords</h3><p>使用形式：{ {  value | truncatewords:2 } }<br>意义：将value切成truncatewords指定的单词数目<br>例如，如果value是Joel is a slug 那么输出将是：Joel is …  </p><h3 id="41、truncatewords-html"><a href="#41、truncatewords-html" class="headerlink" title="41、truncatewords_html"></a>41、truncatewords_html</h3><p>使用形式同(39)<br>意义：truncation点之前如果某个标签打开了，但是没有关闭，那么在truncation点会立即关闭。<br>因为这个操作的效率比truncatewords低，所有只有在value是html格式时，才考虑使用。  </p><h3 id="42、upper"><a href="#42、upper" class="headerlink" title="42、upper"></a>42、upper</h3><p>转换一个字符串为大写形式  </p><h3 id="43、urlencode"><a href="#43、urlencode" class="headerlink" title="43、urlencode"></a>43、urlencode</h3><p>将一个字符串进行URLEncode  </p><h3 id="44、urlize"><a href="#44、urlize" class="headerlink" title="44、urlize"></a>44、urlize</h3><p>意义：将一个字符串中的URL转化成可点击的形式。<br>使用形式：{ {   value | urlize  } }<br>例如，如果value是Check out <a href="http://www.djangoproject.com，那么输出将是：">www.djangoproject.com，那么输出将是：</a><br>Check out <a href="http://www.djangoproject.com">www.djangoproject.com</a>  </p><h3 id="45、urlizetrunc"><a href="#45、urlizetrunc" class="headerlink" title="45、urlizetrunc"></a>45、urlizetrunc</h3><p>使用形式：{ {   value | urlizetrunc:15 } }<br>意义：与(43)相同，但是有一点不同就是现实的链接字符会被truncate成特定的长度，后面以…现实。  </p><h3 id="46、wordcount"><a href="#46、wordcount" class="headerlink" title="46、wordcount"></a>46、wordcount</h3><p>返回字符串中单词的数目  </p><h3 id="47、wordwrap"><a href="#47、wordwrap" class="headerlink" title="47、wordwrap"></a>47、wordwrap</h3><p>使用形式：{ {  value | wordwrap:5 } }<br>意义：按照指定的长度包装字符串<br>例如，如果value是Joel is a slug，那么输出将会是：<br>Joel<br>is a<br>slug  </p><h3 id="48、timesince"><a href="#48、timesince" class="headerlink" title="48、timesince"></a>48、timesince</h3><p>使用形式：{ {  value | timesince:arg } }<br>意义：返回参数arg到value的天数和小时数<br>例如，如果 blog_date 是一个日期实例表示 2006-06-01 午夜， 而 comment_date 是一个日期实例表示 2006-06-01 早上8点，<br>那么 { {   comment_date|timesince:blog_date  } } 将返回 “8 hours”.  </p><h3 id="49、timeuntil"><a href="#49、timeuntil" class="headerlink" title="49、timeuntil"></a>49、timeuntil</h3><p>使用形式：{ {  value | timeuntil } }<br>意义：与(47)基本相同，一个不同点就是，返回的是value距离当前日期的天数和小时数。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django笔记-Luffy</title>
      <link href="python/Django/django-luffy/"/>
      <url>python/Django/django-luffy/</url>
      
        <content type="html"><![CDATA[<h3 id="项目开发基础概念"><a href="#项目开发基础概念" class="headerlink" title="项目开发基础概念"></a>项目开发基础概念</h3><ul><li>企业的web项目类型<ul><li>商城<ul><li>B2C 直销商城 商家与会员直接交易</li><li>B2B 批发商城 商家与商家直接交易</li><li>B2B2C 购物平台 商家和会员在另一个商家提供的平台上面进行交易</li><li>C2B 定制商城 会员向商家发起定制商品的需求,商家去完成</li><li>O2O 线上线下交易平台</li><li>C2C 二手交易平台</li></ul></li><li>门户网站<code>[企业站和门户站]</code></li><li>社交网络</li><li>资讯论坛</li><li>内部系统</li><li>个人博客</li><li>内容收费站</li></ul></li></ul><h3 id="动态的网页"><a href="#动态的网页" class="headerlink" title="动态的网页:"></a>动态的网页:</h3><ul><li>本质上都是字符串的替换</li><li>字符串替换发生在什么地方:<ul><li>在服务器端替换完再返回给浏览器!!!</li></ul></li><li>总结一下:<ol><li>web框架的本质:<ul><li>socket服务端 与 浏览器的通信</li></ul></li><li>socket服务端和功能划分–&gt;<ol start="0"><li>负责与浏览器收发消息:wsgiref/uWsgi/gunicorn</li><li>根据用户访问不同的路径执行不同的函数</li><li>从HTML读取出内容,并且完成字符串的替换–&gt;jinjia2(模板语言)</li></ol></li><li>Python 中 Web框架的分类:<ul><li>按上面三个功能划分:<ol><li>框架自带abc  –&gt; Tornado</li><li>框架自带bc,使用第三方的a  –&gt; Django</li><li>框架自带b,使用第三方的a和c  –&gt; Flask</li></ol></li><li>按另一个维度来划分:<ol><li>Django –&gt; 大而全(你做一个网站能用到的它都有)</li><li>其他 –&gt; Flask 轻量级</li></ol></li></ul></li></ol></li></ul><h3 id="1-HTTP协议消息的格式"><a href="#1-HTTP协议消息的格式" class="headerlink" title="1. HTTP协议消息的格式:"></a>1. HTTP协议消息的格式:</h3><ol><li>请求(request)<ul><li>请求方法 路径 HTTP/1.1</li><li>k1:v1</li><li>…</li><li>请求体     &lt;– 可以有,可以没有</li></ul></li><li>响应(response)<ul><li>HTTP/1.1 状态码 状态描述符</li><li>k1:v1</li><li>Content-Type: text/html; charset=utf8</li><li>响应正文 &lt;– HTML内容</li></ul></li></ol><h3 id="2-Python-web-框架的本质"><a href="#2-Python-web-框架的本质" class="headerlink" title="2. Python web 框架的本质:"></a>2. Python web 框架的本质:</h3><ol><li>收发socket消息   –&gt; 按照HTTP协议消息格式去解析消息</li><li>路径和要执行的函数的对应关系 &lt;– 主要的业务逻辑</li><li>字符串替换 &lt;– 模板(特殊符号, 数据)</li></ol><h3 id="3-一个完整的请求流程"><a href="#3-一个完整的请求流程" class="headerlink" title="3. 一个完整的请求流程:"></a>3. 一个完整的请求流程:</h3><ol start="0"><li>启动服务端,等待客户端(用户的浏览器)来连接</li><li>在浏览器地址输入URL,与服务端建立连接 浏览器发送请求</li><li>服务端收到请求消息,解析请求消息,根据路径和函数对应的关系,找到将要执行的函数</li><li>执行函数,打开HTML文件,进行字符串替换,得到一个最终要返回的HTML内容</li><li>按照HTTP协议的消息格式要求,把HTML内容回复给用户浏览器(发送响应)</li><li>浏览器收到响应的消息之后,按照HTML的规则渲染页面</li><li>关闭连接</li></ol><h3 id="form表单往后端提交数据需要注意哪三点"><a href="#form表单往后端提交数据需要注意哪三点" class="headerlink" title="form表单往后端提交数据需要注意哪三点:"></a>form表单往后端提交数据需要注意哪三点:</h3><ol start="0"><li>form不是from,所有获取用户输入的标签都得放在这里</li><li>action属性控制往哪提交,Method一般都设置成post</li><li>提交按钮必须是type=submit,不能是别的类型</li></ol><h3 id="Django中的APP"><a href="#Django中的APP" class="headerlink" title="Django中的APP"></a>Django中的APP</h3><ol start="0"><li>什么是APP?以及为什么要用APP?<ol start="0"><li>project  –&gt; 项目(老男孩教育大学院)</li><li>app  –&gt; 应用(Linux学院/Python学院/Java学院/大数据学院)</li><li>方便我们在一个大的Django项目中,管理实现不同的业务功能</li><li>创建APP:<ul><li><code>python3 manage.py startapp app_name</code></li></ul></li></ol></li></ol><h3 id="ORM"><a href="#ORM" class="headerlink" title="ORM"></a>ORM</h3><ul><li><p>不同的程序元写的SQL水平参差不齐</p></li><li><p>执行效率也参差不齐</p></li><li><p>Python语法 – 自动翻译–&gt; SQl语句</p></li><li><p>jQuery$(“#d1”)  – 自动翻译–&gt; DOM</p></li></ul><h4 id="优点"><a href="#优点" class="headerlink" title="优点:"></a>优点:</h4><ol start="0"><li>简单,不用自己写SQL语句</li><li>开发效率高</li></ol><h4 id="缺点"><a href="#缺点" class="headerlink" title="缺点:"></a>缺点:</h4><ol><li>记忆特殊的语法</li><li>相对于大神写的SQL语句,肯定执行效率有差距</li></ol><h4 id="ORM的对应关系"><a href="#ORM的对应关系" class="headerlink" title="ORM的对应关系:"></a>ORM的对应关系:</h4><ul><li>类   –&gt; 数据表</li><li>对象   –&gt; 数据行</li><li>属性   –&gt; 字段</li></ul><h4 id="ORM能做的事儿"><a href="#ORM能做的事儿" class="headerlink" title="ORM能做的事儿:"></a>ORM能做的事儿:</h4><ol start="0"><li>操作数据表    –&gt; 创建表/删除表/修改表</li><li>操作数据行    –&gt; 数据的增删改查<br>不能创建数据库</li></ol><h3 id="使用django的ORM详细步骤"><a href="#使用django的ORM详细步骤" class="headerlink" title="使用django的ORM详细步骤:"></a>使用django的ORM详细步骤:</h3><ol><li>自己动手创建数据库    </li><li>在django项目中设置连接数据库的相关配置(告诉django要连哪个数据库)</li><li>告诉django用pymysql代替默认mysqldb去连接数据库    </li><li>在app下面的models.py中定义一个类,这个类必须继承models.model</li><li>执行两个命令<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">python3 manage.py makemigrations</span><br><span class="line">python3 manage.py makemigrate</span><br></pre></td></tr></table></figure></li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>什么是wsgi？</title>
      <link href="python/Django/python-wsgi/"/>
      <url>python/Django/python-wsgi/</url>
      
        <content type="html"><![CDATA[<p>本文转自:<a href="https://www.jianshu.com/p/c66d3adeaaed">https://www.jianshu.com/p/c66d3adeaaed</a></p><p>WSGI的全称是<em>Web Server Gateway Interface</em>，翻译过来就是<em>Web服务器网关接口</em>。具体的来说，<strong>WSGI是一个规范，定义了Web服务器如何与Python应用程序进行交互，使得使用Python写的Web应用程序可以和Web服务器对接起来</strong>。WSGI一开始是在<a        href="https://www.python.org/dev/peps/pep-0333/" target="_blank" rel="nofollow">PEP-0333</a>中定义的，最新版本是在Python的<a        href="https://www.python.org/dev/peps/pep-3333/" target="_blank" rel="nofollow">PEP-3333</a>定义的。</p><h1>WSGI是什么</h1><p>WSGI的全称是<em>Web Server Gateway Interface</em>，翻译过来就是<em>Web服务器网关接口</em>。具体的来说，<strong>WSGI是一个规范，定义了Web服务器如何与Python应用程序进行交互，使得使用Python写的Web应用程序可以和Web服务器对接起来</strong>。WSGI一开始是在<a        href="https://www.python.org/dev/peps/pep-0333/" target="_blank" rel="nofollow">PEP-0333</a>中定义的，最新版本是在Python的<a        href="https://www.python.org/dev/peps/pep-3333/" target="_blank" rel="nofollow">PEP-3333</a>定义的。</p><p>对于初学者来说，上面那段就是废话，说了跟没说一样。本文的主要内容就是说清楚，WSGI到底是如何工作的。</p><h2>为什么需要WSGI这个规范</h2><p>在Web部署的方案上，有一个方案是目前应用最广泛的：</p><ul>    <li><p>首先，部署一个Web服务器专门用来处理HTTP协议层面相关的事情，比如如何在一个物理机上提供多个不同的Web服务（单IP多域名，单IP多端口等）这种事情。</p></li>    <li><p>然后，部署一个用各种语言编写（Java, PHP, Python,        Ruby等）的应用程序，这个应用程序会从Web服务器上接收客户端的请求，处理完成后，再返回响应给Web服务器，最后由Web服务器返回给客户端。</p></li></ul><p>    那么，要采用这种方案，Web服务器和应用程序之间就要知道如何进行交互。为了定义Web服务器和应用程序之间的交互过程，就形成了很多不同的规范。这种规范里最早的一个是CGI][3，1993年开发的。后来又出现了很多这样的规范。比如改进CGI性能的FasgCGI，Java专用的Servlet规范，还有Python专用的WSGI规范等。提出这些规范的目的就是为了定义统一的标准，提升程序的可移植性。在WSGI规范的最开始的PEP-333中一开始就描述了为什么需要WSGI规范。</p><h1>WSGI如何工作</h1><p>从上文可以知道，WSGI相当于是Web服务器和Python应用程序之间的桥梁。那么这个桥梁是如何工作的呢？首先，我们明确桥梁的作用，WSGI存在的目的有两个：</p><ol>    <li><p>让Web服务器知道如何调用Python应用程序，并且把用户的请求告诉应用程序。</p></li>    <li><p>让Python应用程序知道用户的具体请求是什么，以及如何返回结果给Web服务器。</p></li></ol><h2>WSGI中的角色</h2><p>    在WSGI中定义了两个角色，Web服务器端称为<strong>server</strong>或者<strong>gateway</strong>，应用程序端称为<strong>application</strong>或者<strong>framework</strong>（因为WSGI的应用程序端的规范一般都是由具体的框架来实现的）。我们下面统一使用server和application这两个术语。</p><p>server端会先收到用户的请求，然后会根据规范的要求调用application端，如下图所示：</p><p>[图片上传失败...(image-1bd5a9-1541121120404)]</p><p>调用的结果会被封装成HTTP响应后再发送给客户端。</p><h2>server如何调用application</h2><p>首先，每个application的入口只有一个，也就是所有的客户端请求都同一个入口进入到应用程序。</p><p>    接下来，server端需要知道去哪里找application的入口。这个需要在server端指定一个Python模块，也就是Python应用中的一个文件，并且这个模块中需要包含一个名称为<strong>application</strong>的可调用对象（函数和类都可以），这个<strong>application</strong>对象就是这个应用程序的唯一入口了。WSGI还定义了<strong>application</strong>对象的形式：</p><pre class="line-numbers  language-python"><code class="  language-python"><span        class="token keyword">def</span> <span class="token function">simple_app</span><span        class="token punctuation">(</span>environ<span class="token punctuation">,</span> start_response<span        class="token punctuation">)</span><span class="token punctuation">:</span>      <span class="token keyword">pass</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>上面代码中的<code>environ</code>和<code>start_response</code>就是server端调用<strong>application</strong>对象时传递的两个参数。</p><p>    我们来看具体的例子。假设我们的应用程序的入口文件是<code>/var/www/index.py</code>，那么我们就需要在server端配置好这个路径（如何配置取决于server端的实现），然后在<code>index.py</code>中的代码如下所示：</p><p>使用标准库（这个只是demo）</p><pre class="line-numbers  language-swift"><code class="  language-swift"><span class="token keyword">import</span> wsgiref<p>application <span class="token operator">=</span> wsgiref<span class="token punctuation">.</span>simple_server<span            class="token punctuation">.</span>demo_app<br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>使用web.py框架</p><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">import</span> web<p>urls <span class="token operator">=</span> <span class="token punctuation">(</span><br>    <span class="token string">‘/.*’</span><span class="token punctuation">,</span> <span            class="token string">‘hello’</span><span class="token punctuation">,</span><br><span class="token punctuation">)</span></p><p><span class="token keyword">class</span> <span class="token class-name">hello</span><span            class="token punctuation">(</span><span class="token builtin">object</span><span            class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">def</span> <span class="token function">GET</span><span            class="token punctuation">(</span>self<span class="token punctuation">)</span><span            class="token punctuation">:</span><br>        <span class="token keyword">return</span> <span class="token string">“Hello, world.”</span></p><p>application <span class="token operator">=</span> web<span class="token punctuation">.</span>application<span            class="token punctuation">(</span>urls<span class="token punctuation">,</span> <span            class="token builtin">globals</span><span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><span            class="token punctuation">.</span>wsgifunc<span class="token punctuation">(</span><span            class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>你可以看到，文件中都需要有一个<strong>application</strong>对象，server端会找到这个文件，然后调用这个对象。所以支持WSGI的Python框架最终都会有这么一个application对象，不过框架的使用者不需要关心这个application对象内部是如何工作的，只需要关心路由定义、请求处理等具体的业务逻辑。</p><p>因为application对象是唯一的入口，所以不管客户端请求的路径和数据是什么，server都是调用这个application对象，具体的客户端请求的处理有application对象完成。</p><h2>application对象需要做什么</h2><p>上面已经提到了，application对象需要是一个可调用对象，而且其定义需要满足如下形式：</p><pre class="line-numbers  language-python"><code class="  language-python"><span        class="token keyword">def</span> <span class="token function">simple_app</span><span        class="token punctuation">(</span>environ<span class="token punctuation">,</span> start_response<span        class="token punctuation">)</span><span class="token punctuation">:</span>      <span class="token keyword">pass</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>    当server按照WSGI的规范调用了application之后，application就可以开始处理客户端的请求了，处理请求之后，application对象需要返回处理结果给server端。处理请求和返回结果这两个事情，都和server调用application对象时传递的两个参数有关。</p><h3>environ参数</h3><p>    environ参数是一个Python的字典，里面存放了所有和客户端相关的信息，这样application对象就能知道客户端请求的资源是什么，请求中带了什么数据等。environ字典包含了一些CGI规范要求的数据，以及WSGI规范新增的数据，还可能包含一些操作系统的环境变量以及Web服务器相关的环境变量。我们来看一些environ中常用的成员：</p><p>首先是CGI规范中要求的变量：</p><ul>    <li><p><strong>REQUEST_METHOD</strong>： 请求方法，是个字符串，'GET', 'POST'等</p></li>    <li><p><strong>SCRIPT_NAME</strong>： HTTP请求的path中的用于查找到application对象的部分，比如Web服务器可以根据path的一部分来决定请求由哪个virtual        host处理</p></li>    <li><p><strong>PATH_INFO</strong>： HTTP请求的path中剩余的部分，也就是application要处理的部分</p></li>    <li><p><strong>QUERY_STRING</strong>： HTTP请求中的查询字符串，URL中<strong>?</strong>后面的内容</p></li>    <li><p><strong>CONTENT_TYPE</strong>： HTTP headers中的content-type内容</p></li>    <li><p><strong>CONTENT_LENGTH</strong>： HTTP headers中的content-length内容</p></li>    <li><p><strong>SERVER_NAME</strong>和<strong>SERVER_PORT</strong>： 服务器名和端口，这两个值和前面的SCRIPT_NAME,        PATH_INFO拼起来可以得到完整的URL路径</p></li>    <li><p><strong>SERVER_PROTOCOL</strong>： HTTP协议版本，HTTP/1.0或者HTTP/1.1</p></li>    <li><p><strong>HTTP_</strong>： 和HTTP请求中的headers对应。</p></li></ul><p>WSGI规范中还要求environ包含下列成员：</p><ul>    <li><p><strong>wsgi.version</strong>：表示WSGI版本，一个元组(1, 0)，表示版本1.0</p></li>    <li><p><strong>wsgi.url_scheme</strong>：http或者https</p></li>    <li><p><strong>wsgi.input</strong>：一个类文件的输入流，application可以通过这个获取HTTP request body</p></li>    <li><p><strong>wsgi.errors</strong>：一个输出流，当应用程序出错时，可以将错误信息写入这里</p></li>    <li><p><strong>wsgi.multithread</strong>：当application对象可能被多个线程同时调用时，这个值需要为True</p></li>    <li><p><strong>wsgi.multiprocess</strong>：当application对象可能被多个进程同时调用时，这个值需要为True</p></li>    <li><p><strong>wsgi.run_once</strong>：当server期望application对象在进程的生命周期内只被调用一次时，该值为True</p></li></ul><p>上面列出的这些内容已经包括了客户端请求的所有数据，足够application对象处理客户端请求了。</p><h3>start_resposne参数</h3><p>start_response是一个可调用对象，接收两个必选参数和一个可选参数：</p><ul>    <li><p><strong>status</strong>: 一个字符串，表示HTTP响应状态字符串</p></li>    <li><p><strong>response_headers</strong>: 一个列表，包含有如下形式的元组：(header_name, header_value)，用来表示HTTP响应的headers</p>    </li>    <li><p><strong>exc_info</strong>（可选）: 用于出错时，server需要返回给浏览器的信息</p></li></ul><p>    当application对象根据environ参数的内容执行完业务逻辑后，就需要返回结果给server端。我们知道HTTP的响应需要包含status，headers和body，所以在application对象将body作为返回值return之前，需要先调用<code>start_response()</code>，将status和headers的内容返回给server，这同时也是告诉server，application对象要开始返回body了。</p><h3>application对象的返回值</h3><p>    application对象的返回值用于为HTTP响应提供body，如果没有body，那么可以返回None。如果有body的化，那么需要返回一个可迭代的对象。server端通过遍历这个可迭代对象可以获得body的全部内容。</p><h3>application demo</h3><p>PEP-3333中有一个application的实现demo，我把它再简化之后如下：</p><pre class="line-numbers  language-python"><code class="  language-python"><span        class="token keyword">def</span> <span class="token function">simple_app</span><span        class="token punctuation">(</span>environ<span class="token punctuation">,</span> start_response<span        class="token punctuation">)</span><span class="token punctuation">:</span>      status <span class="token operator">=</span> <span class="token string">'200 OK'</span>      response_headers <span class="token operator">=</span> <span class="token punctuation">[</span><span            class="token punctuation">(</span><span class="token string">'Content-type'</span><span            class="token punctuation">,</span> <span class="token string">'text/plain'</span><span            class="token punctuation">)</span><span class="token punctuation">]</span>      start_response<span class="token punctuation">(</span>status<span class="token punctuation">,</span> response_headers<span            class="token punctuation">)</span>      <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string">'hello, world'</span><span            class="token punctuation">]</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>可以将这段代码和前面的说明对照起来理解。</p><h2>再谈server如何调用application</h2><p>    前面已经知道server如何定位到application的入口了，也知道了application的入口的形式以及application对象内部需要完成的工作。那么，我们还需要再说一下，<code>environ</code>和<code>start_response()</code>是需要在server端的生成和定义的，其中关于<code>start_response()</code>的部分在规范中也有明确的要求。这部分内容太长了，不适合放在本文中，有兴趣的读者可以去看下PEP-3333，里面有一段server端的demo实现。</p><h1>WSGI中间件</h1><p><strong>WSGI Middleware</strong>（中间件）也是WSGI规范的一部分。上一章我们已经说明了WSGI的两个角色：server和application。那么middleware是一种运行在server和application中间的应用（一般都是Python应用）。middleware同时具备server和application角色，对于server来说，它是一个application；对于application来说，它是一个server。middleware并不修改server端和application端的规范，只是同时实现了这两个角色的功能而已。</p><p>我们可以通过下图来说明middleware是如何工作的：</p><div class="image-package">    <div class="image-container" style="max-width: 700px; max-height: 632px;">        <div class="image-container-fill" style="padding-bottom: 87.9%;"></div>        <div class="image-view" data-width="719" data-height="632"><img                data-original-src="//upload-images.jianshu.io/upload_images/12899159-c08bb71a5e61b087.png"                data-original-width="719" data-original-height="632" data-original-format="image/png"                data-original-filesize="55852" class="image-loading" data-image-index="0" style="cursor: zoom-in;">        </div>    </div>    <div class="image-caption">755097673-55c76463de432_articlex.png</div></div><p>上图中最上面的三个彩色框表示角色，中间的白色框表示操作，操作的发生顺序按照1 ~ 5进行了排序，我们直接对着上图来说明middleware是如何工作的：</p><ol>    <li><p>Server收到客户端的HTTP请求后，生成了<code>environ_s</code>，并且已经定义了<code>start_response_s</code>。</p></li>    <li><p>Server调用Middleware的application对象，传递的参数是<code>environ_s</code>和<code>start_response_s</code>。</p></li>    <li><p>Middleware会根据<code>environ</code>执行业务逻辑，生成<code>environ_m</code>，并且已经定义了<code>start_response_m</code>。    </p></li>    <li><p>Middleware决定调用Application的application对象，传递参数是<code>environ_m</code>和<code>start_response_m</code>。Application的application对象处理完成后，会调用<code>start_response_m</code>并且返回结果给Middleware，存放在<code>result_m</code>中。    </p></li>    <li><p>Middleware处理<code>result_m</code>，然后生成<code>result_s</code>，接着调用<code>start_response_s</code>，并返回结果<code>result_s</code>给Server端。Server端获取到result_s后就可以发送结果给客户端了。    </p></li></ol><p>从上面的流程可以看出middleware应用的几个特点：</p><ol>    <li><p>Server认为middleware是一个application。</p></li>    <li><p>Application认为middleware是一个server。</p></li>    <li><p>Middleware可以有多层。</p></li></ol><p>因为Middleware能过处理所有经过的request和response，所以要做什么都可以，没有限制。比如可以检查request是否有非法内容，检查response是否有非法内容，为request加上特定的HTTP    header等，这些都是可以的。</p><h1>WSGI的实现和部署</h1><p>要使用WSGI，需要分别实现server角色和application角色。</p><p>Application端的实现一般是由Python的各种框架来实现的，比如Django, web.py等，一般开发者不需要关心WSGI的实现，框架会会提供接口让开发者获取HTTP请求的内容以及发送HTTP响应。</p><p>    Server端的实现会比较复杂一点，这个主要是因为软件架构的原因。一般常用的Web服务器，如Apache和nginx，都不会内置WSGI的支持，而是通过扩展来完成。比如Apache服务器，会通过扩展模块mod_wsgi来支持WSGI。Apache和mod_wsgi之间通过程序内部接口传递信息，mod_wsgi会实现WSGI的server端、进程管理以及对application的调用。Nginx上一般是用proxy的方式，用nginx的协议将请求封装好，发送给应用服务器，比如uWSGI，应用服务器会实现WSGI的服务端、进程管理以及对application的调用。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>对python中变量值交换的一些思考</title>
      <link href="cp/python/python-change-var/"/>
      <url>cp/python/python-change-var/</url>
      
        <content type="html"><![CDATA[<p>本文转载自:<a href="https://www.jianshu.com/p/0a80f376c7f3">https://www.jianshu.com/p/0a80f376c7f3</a></p><p>简书不维护了，欢迎关注我的知乎：<a        href="https://links.jianshu.com/go?to=https%3A%2F%2Fwww.zhihu.com%2Fpeople%2Fxue-jian-27%2Factivities"        target="_blank" rel="nofollow">波罗学的个人主页</a></p><p>知乎地址：<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F58691979" target="_blank"           rel="nofollow">https://zhuanlan.zhihu.com/p/58691979</a></p><p>在编程中，一旦提到变量值的交换，脑海中最先浮现的做法就是引入一个临时变量作为媒介来做，来看看具体的实现。</p><h2>解决方案</h2><p>先假设有两个变量x、y，如下：</p><pre class="line-numbers  language-python"><code class="python  language-python">x <span        class="token operator">=</span> <span class="token number">10</span>y <span class="token operator">=</span> <span class="token number">20</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p><strong>常见方案</strong>，定义一个临时变量作为媒介，实现变量值的交换。实现如下：</p><pre class="line-numbers  language-python"><code class="python  language-python">t <span        class="token operator">=</span> xx <span class="token operator">=</span> yy <span class="token operator">=</span> t<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p><strong>pythonic</strong>，对于这种需求其实python为我们提供了一种更方便的解决方案。</p><pre class="line-numbers  language-python"><code class="python  language-python">x<span        class="token punctuation">,</span> y <span class="token operator">=</span> y<span        class="token punctuation">,</span> x<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>从代码上就可以直观的理解此处的意图，即实现x与y变量值的交换。</p><p>到这里都非常容易理解，但是接下来我们需要思考一下：此写法性能如何？为什么可以如此便捷地就是实现了变量值交换？</p><h2>性能比较</h2><p>虽然写法简洁方便，但是是否已损耗性能为代价呢？定义两个函数：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">def</span> <span class="token function">swap1</span><span        class="token punctuation">(</span><span class="token punctuation">)</span><span        class="token punctuation">:</span>    x <span class="token operator">=</span> <span class="token number">1</span>    y <span class="token operator">=</span> <span class="token number">2</span>    t <span class="token operator">=</span> x     x <span class="token operator">=</span> y    y <span class="token operator">=</span> t<p><span class="token keyword">def</span> <span class="token function">swap2</span><span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">:</span><br>    x <span class="token operator">=</span> <span class="token number">1</span><br>    y <span class="token operator">=</span> <span class="token number">2</span><br>    x<span class="token punctuation">,</span> y <span class="token operator">=</span> y<span            class="token punctuation">,</span> x<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>为了更好的看出性能差异，循环调用分别调用两函数100次（需要在ipython中执行）：</p><p>swap1耗时38µs</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">%</span>time a <span class="token operator">=</span> <span        class="token punctuation">[</span>swap1<span        class="token punctuation">(</span><span class="token punctuation">)</span> <span        class="token keyword">for</span> _ <span class="token keyword">in</span> <span        class="token builtin">range</span><span class="token punctuation">(</span><span        class="token number">100</span><span class="token punctuation">)</span><span        class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>结果如下：</p><pre class="line-numbers  language-bash"><code class="  language-bash">CPU times: user 31 µs, sys: 7 µs, total: 38 µsWall time: 67 µs<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>swap2耗时18µs</p><pre class="line-numbers  language-python"><code class="python  language-python"> <span        class="token operator">%</span>time a <span class="token operator">=</span> <span        class="token punctuation">[</span>swap2<span        class="token punctuation">(</span><span class="token punctuation">)</span> <span        class="token keyword">for</span> _ <span class="token keyword">in</span> <span        class="token builtin">range</span><span class="token punctuation">(</span><span        class="token number">100</span><span class="token punctuation">)</span><span        class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>结果如下：</p><pre class="line-numbers  language-bash"><code class="  language-bash">CPU times: user 18 µs, sys: 0 ns, total: 18 µsWall time: 21 µs<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>可以看出pythonic的写法比简单粗暴的引入新的辅助变量要快很多。写法如此简洁而且性能高，何乐而不为呢。</p><p>补充：这有一篇文章 <a href="https://links.jianshu.com/go?to=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F35095687"                target="_blank" rel="nofollow">python面试值交换变量值</a> 从底层解释了两种方式性能上差异的原因。</p><h2>多些思考</h2><p>那么下面再思考一个问题：为什么python可以用这种写法来赋值呢？</p><p>看一些赋值运算符右边的表达式，即 y, x，这实际在python中称为<strong>元组</strong>的数据结构。我们可以看到赋值表达式左边是 x, y，那么为什么元组可以直接赋值给 x,y 呢？</p><p>此处利用了python的一个特性，即任何序列（或可迭代的对象）都可以通过简单的赋值操作分解为单独的变量。我们再来看一个例子：</p><pre class="line-numbers  language-python"><code class="python  language-python">name<span        class="token punctuation">,</span> age<span class="token punctuation">,</span> mobile <span        class="token operator">=</span> <span class="token string">'polo'</span><span        class="token punctuation">,</span> <span class="token number">30</span><span        class="token punctuation">,</span> <span class="token string">'15312210823'</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>执行以上代码便可将name赋值为polo，age赋值为30，phone赋值为15312210823。</p><h2>延伸扩展</h2><p>除了以上这种简单序列的拆解，python同样支持其他更复杂的场景，下面来看看多层嵌套变量的分解，例子最直观：</p><pre class="line-numbers  language-python"><code class="python  language-python">school_name<span        class="token punctuation">,</span> <span class="token punctuation">(</span>student_name<span        class="token punctuation">,</span> stduent_age<span class="token punctuation">,</span> stduent_sex<span        class="token punctuation">)</span> <span class="token operator">=</span> <span        class="token string">'致远中学'</span><span class="token punctuation">,</span> <span        class="token punctuation">(</span><span class="token string">'polo'</span><span        class="token punctuation">,</span> <span class="token number">18</span><span        class="token punctuation">,</span> <span class="token string">'M'</span><span        class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>也可以支持不定长序列的灵活分解，比如现在有一个班级已排序的学生成绩列表，如下：</p><pre class="line-numbers  language-python"><code class="python  language-python">scores <span        class="token operator">=</span> <span class="token punctuation">[</span><span        class="token number">21</span><span        class="token punctuation">,</span> <span class="token number">34</span><span        class="token punctuation">,</span> <span class="token number">36</span><span        class="token punctuation">,</span> <span class="token number">56</span><span        class="token punctuation">,</span> <span class="token number">60</span><span        class="token punctuation">,</span> <span class="token number">75</span><span        class="token punctuation">,</span> <span class="token number">76</span><span        class="token punctuation">,</span> <span class="token number">81</span><span        class="token punctuation">,</span> <span class="token number">83</span><span        class="token punctuation">,</span> <span class="token number">86</span><span        class="token punctuation">,</span> <span class="token number">86</span><span        class="token punctuation">,</span> <span class="token number">89</span><span        class="token punctuation">,</span> <span class="token number">90</span><span        class="token punctuation">,</span> <span class="token number">95</span><span        class="token punctuation">,</span> <span class="token number">98</span><span        class="token punctuation">,</span> <span class="token number">99</span><span        class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>我们的目标获取成绩最大、最小和其他学生的成绩列表，直接通过序列的分解便可快速得到需要的数据：</p><pre class="line-numbers  language-python"><code class="python  language-python">min_score<span        class="token punctuation">,</span> <span class="token operator">*</span>other_scores<span        class="token punctuation">,</span> max_score <span class="token operator">=</span> scores<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>这里引入了一种新的写法，*表达式变量 轻松分解出中间的可迭代对象并赋值给other_scores，同时将开头和结束的对象分别赋值给min_score和max_score。</p><p>看到这里感觉序列分解似乎有点类似于正则表达式的模式匹配。</p><h2>总结</h2><p>虽然只是小小的变量值的交换，但本质也是由需求和语言自身特性决定的。学会一些必要的技巧，将会帮助我们写出更高质量的代码。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python中什么是元类metaclass？</title>
      <link href="cp/python/python-metaclass/"/>
      <url>cp/python/python-metaclass/</url>
      
        <content type="html"><![CDATA[<blockquote>    <p>原文地址：<a            href="https://link.jianshu.com?t=http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python/6581949#6581949"            target="_blank" rel="nofollow">what is metaclass in Python?</a><br>        此文为原译，如需转载，请联系作者<br>        我的简书地址：<a href="https://www.jianshu.com/users/69ba0aedbe3c/latest_articles" target="_blank">:nummy</a></p></blockquote><h3>类即对象</h3><p>在理解元类之前，需要先掌握Python中的类，Python中类的概念与SmallTalk中类的概念相似。<br>    在大多数语言中，类是用来描述如何创建对象的代码段，这在Python中也是成立的：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">class</span> <span class="token class-name">ObjectCreator</span><span        class="token punctuation">(</span><span class="token builtin">object</span><span        class="token punctuation">)</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>       <span            class="token keyword">pass</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <p><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> my_object <span            class="token operator">=</span> ObjectCreator<span class="token punctuation">(</span><span            class="token punctuation">)</span><br><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>my_object<span            class="token punctuation">)</span><br><span class="token operator">&lt;</span><strong>main</strong><span class="token punctuation">.</span>ObjectCreator <span            class="token builtin">object</span> at <span class="token number">0x8974f2c</span><span            class="token operator">&gt;</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>    Python中，类其实也是对象。当我们使用关键字<strong>class</strong>的时候，Python会执行这段代码，然后生成一个对象。下面的代码在内存中创建一个对象<code>ObjectCreator</code>:</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">class</span> <span class="token class-name">ObjectCreator</span><span        class="token punctuation">(</span><span class="token builtin">object</span><span        class="token punctuation">)</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>       <span            class="token keyword">pass</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p><strong>当一个对象具有创建对象的能力时，就称该对象为类。</strong></p><p>所以类本质上还是一个对象，因此它具有以下属性：</p><ul>    <li>可以将它赋值给其它变量</li>    <li>可以对它进行复制</li>    <li>可以给它添加属性</li>    <li>可以将它传递给函数作为参数</li></ul><p>例如：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">print</span><span        class="token punctuation">(</span>ObjectCreator<span class="token punctuation">)</span> <span        class="token comment"># you can print a class because it's an object</span><span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token string">'__main__.ObjectCreator'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">def</span> <span class="token function">echo</span><span            class="token punctuation">(</span>o<span class="token punctuation">)</span><span            class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>       <span            class="token keyword">print</span><span class="token punctuation">(</span>o<span            class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> echo<span            class="token punctuation">(</span>ObjectCreator<span class="token punctuation">)</span> <span            class="token comment"># you can pass a class as a parameter</span><span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token string">'__main__.ObjectCreator'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">hasattr</span><span            class="token punctuation">(</span>ObjectCreator<span class="token punctuation">,</span> <span            class="token string">'new_attribute'</span><span class="token punctuation">)</span><span            class="token punctuation">)</span><span class="token boolean">False</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> ObjectCreator<span            class="token punctuation">.</span>new_attribute <span class="token operator">=</span> <span            class="token string">'foo'</span> <span class="token comment"># you can add attributes to a class</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">hasattr</span><span            class="token punctuation">(</span>ObjectCreator<span class="token punctuation">,</span> <span            class="token string">'new_attribute'</span><span class="token punctuation">)</span><span            class="token punctuation">)</span><span class="token boolean">True</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>ObjectCreator<span            class="token punctuation">.</span>new_attribute<span class="token punctuation">)</span>foo<span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> ObjectCreatorMirror <span            class="token operator">=</span> ObjectCreator <span class="token comment"># you can assign a class to a variable</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>ObjectCreatorMirror<span            class="token punctuation">.</span>new_attribute<span class="token punctuation">)</span>foo<span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>ObjectCreatorMirror<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">)</span><span class="token operator">&lt;</span>__main__<span class="token punctuation">.</span>ObjectCreator <span            class="token builtin">object</span> at <span class="token number">0x8997b4c</span><span            class="token operator">&gt;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><h3>动态创建类</h3><p>既然类就是对象，那我们就可以像创建其他对象一样动态创建类。<br>    首先，在函数中使用class创建一个类：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">def</span> <span class="token function">choose_class</span><span        class="token punctuation">(</span>name<span class="token punctuation">)</span><span        class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>     <span            class="token keyword">if</span> name <span class="token operator">==</span> <span            class="token string">'foo'</span><span            class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>         <span            class="token keyword">class</span> <span class="token class-name">Foo</span><span            class="token punctuation">(</span><span class="token builtin">object</span><span            class="token punctuation">)</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>             <span            class="token keyword">pass</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>         <span            class="token keyword">return</span> Foo <span            class="token comment"># return the class, not an instance</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>     <span            class="token keyword">else</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>         <span            class="token keyword">class</span> <span class="token class-name">Bar</span><span            class="token punctuation">(</span><span class="token builtin">object</span><span            class="token punctuation">)</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>             <span            class="token keyword">pass</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>         <span            class="token keyword">return</span> Bar<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>     <span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> MyClass <span            class="token operator">=</span> choose_class<span class="token punctuation">(</span><span            class="token string">'foo'</span><span class="token punctuation">)</span> <span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>MyClass<span            class="token punctuation">)</span> <span class="token comment"># the function returns a class, not an instance</span><span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token string">'__main__.Foo'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>MyClass<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">)</span> <span            class="token comment"># you can create an object from this class</span><span class="token operator">&lt;</span>__main__<span class="token punctuation">.</span>Foo <span class="token builtin">object</span> at <span            class="token number">0x89c6d4c</span><span class="token operator">&gt;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>但是上面的例子也称不上是完全动态的创建类，因为我们还需要在其中编写整个类的代码。<br>    既然类就是对象，那么它们肯定是通过某个东西来创建的。当使用<strong>class</strong>关键字的时候，Python会自动创建类，Python也提供了方法让我们手动来创建类。</p><p>还记得<strong>type()</strong>函数吗？这个函数可以获取对象的类型。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">print</span><span        class="token punctuation">(</span><span class="token builtin">type</span><span        class="token punctuation">(</span><span class="token number">1</span><span        class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token builtin">type</span> <span            class="token string">'int'</span><span class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span><span            class="token builtin">type</span><span            class="token punctuation">(</span><span class="token string">"1"</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token builtin">type</span> <span            class="token string">'str'</span><span class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span><span            class="token builtin">type</span><span            class="token punctuation">(</span>ObjectCreator<span class="token punctuation">)</span><span            class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token builtin">type</span> <span class="token string">'type'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span><span            class="token builtin">type</span><span            class="token punctuation">(</span>ObjectCreator<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><span            class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token string">'__main__.ObjectCreator'</span><span            class="token operator">&gt;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p><strong>type</strong>还有另外一个功能，那就是创建类。<strong>type</strong>使用类的相关描述作为参数，然后返回一个类。<br>    <strong>type</strong>创建类的语法如下：</p><pre class="line-numbers  language-bash"><code class="  language-bash">type(类名,基类元组(可以为空，用于继承), 包含属性或函数的字典)<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>例如：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">class</span> <span class="token class-name">MyShinyClass</span><span        class="token punctuation">(</span><span class="token builtin">object</span><span        class="token punctuation">)</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>       <span            class="token keyword">pass</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>上面的类可以使用下面的方法手动创建：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> MyShinyClass <span class="token operator">=</span> <span        class="token builtin">type</span><span class="token punctuation">(</span><span class="token string">'MyShinyClass'</span><span        class="token punctuation">,</span> <span class="token punctuation">(</span><span        class="token punctuation">)</span><span class="token punctuation">,</span> <span        class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span        class="token punctuation">)</span> <span class="token comment"># returns a class object</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>MyShinyClass<span            class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token string">'__main__.MyShinyClass'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>MyShinyClass<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">)</span> <span            class="token comment"># create an instance with the class</span><span class="token operator">&lt;</span>__main__<span class="token punctuation">.</span>MyShinyClass <span            class="token builtin">object</span> at <span class="token number">0x8997cec</span><span            class="token operator">&gt;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p><strong>type</strong>也接收一个字典参数来定义类中的属性：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">class</span> <span        class="token class-name">Foo</span><span        class="token punctuation">(</span><span class="token builtin">object</span><span        class="token punctuation">)</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>       bar <span            class="token operator">=</span> <span class="token boolean">True</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>等价于</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> Foo <span class="token operator">=</span> <span        class="token builtin">type</span><span        class="token punctuation">(</span><span class="token string">'Foo'</span><span        class="token punctuation">,</span> <span class="token punctuation">(</span><span        class="token punctuation">)</span><span class="token punctuation">,</span> <span        class="token punctuation">&#123;</span><span class="token string">'bar'</span><span        class="token punctuation">:</span><span class="token boolean">True</span><span        class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>通过<code>type</code>创建的类使用方式跟普通类一样：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">print</span><span        class="token punctuation">(</span>Foo<span class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token string">'__main__.Foo'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>Foo<span            class="token punctuation">.</span>bar<span class="token punctuation">)</span><span class="token boolean">True</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> f <span            class="token operator">=</span> Foo<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>f<span            class="token punctuation">)</span><span class="token operator">&lt;</span>__main__<span class="token punctuation">.</span>Foo <span class="token builtin">object</span> at <span            class="token number">0x8a9b84c</span><span class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>f<span            class="token punctuation">.</span>bar<span class="token punctuation">)</span><span class="token boolean">True</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>当然也可以继承：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span>   <span class="token keyword">class</span> <span        class="token class-name">FooChild</span><span class="token punctuation">(</span>Foo<span        class="token punctuation">)</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>         <span            class="token keyword">pass</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>等价于：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> FooChild <span class="token operator">=</span> <span        class="token builtin">type</span><span class="token punctuation">(</span><span        class="token string">'FooChild'</span><span        class="token punctuation">,</span> <span class="token punctuation">(</span>Foo<span        class="token punctuation">,</span><span class="token punctuation">)</span><span        class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span        class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>FooChild<span            class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token string">'__main__.FooChild'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">print</span><span class="token punctuation">(</span>FooChild<span            class="token punctuation">.</span>bar<span class="token punctuation">)</span> <span            class="token comment"># bar is inherited from Foo</span><span class="token boolean">True</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>最后，我们可能还想给类添加方法，可以先定义一个函数，然后将它以属性的方式赋予给类。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">def</span> <span        class="token function">echo_bar</span><span        class="token punctuation">(</span>self<span class="token punctuation">)</span><span        class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>       <span            class="token keyword">print</span><span class="token punctuation">(</span>self<span            class="token punctuation">.</span>bar<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> FooChild <span            class="token operator">=</span> <span class="token builtin">type</span><span            class="token punctuation">(</span><span class="token string">'FooChild'</span><span            class="token punctuation">,</span> <span class="token punctuation">(</span>Foo<span            class="token punctuation">,</span><span class="token punctuation">)</span><span            class="token punctuation">,</span> <span class="token punctuation">&#123;</span><span class="token string">'echo_bar'</span><span            class="token punctuation">:</span> echo_bar<span class="token punctuation">&#125;</span><span            class="token punctuation">)</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token builtin">hasattr</span><span class="token punctuation">(</span>Foo<span            class="token punctuation">,</span> <span class="token string">'echo_bar'</span><span            class="token punctuation">)</span><span class="token boolean">False</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token builtin">hasattr</span><span class="token punctuation">(</span>FooChild<span            class="token punctuation">,</span> <span class="token string">'echo_bar'</span><span            class="token punctuation">)</span><span class="token boolean">True</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> my_foo <span            class="token operator">=</span> FooChild<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> my_foo<span            class="token punctuation">.</span>echo_bar<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token boolean">True</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>而且，我们还可以在动态创建类之后，给类添加更多的方法和属性：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">def</span> <span class="token function">echo_bar_more</span><span        class="token punctuation">(</span>self<span class="token punctuation">)</span><span        class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>       <span            class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'yet another method'</span><span            class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> FooChild<span            class="token punctuation">.</span>echo_bar_more <span class="token operator">=</span> echo_bar_more<span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token builtin">hasattr</span><span class="token punctuation">(</span>FooChild<span            class="token punctuation">,</span> <span class="token string">'echo_bar_more'</span><span            class="token punctuation">)</span><span class="token boolean">True</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><h3>什么是元类？</h3><p>通常，我们定义类来创建对象，但是现在我们知道类也是对象。那么是通过什么来创建类呢？答案就是元类。你可以想象关系如下：</p><pre class="line-numbers  language-python"><code class="python  language-python">MyClass <span        class="token operator">=</span> MetaClass<span class="token punctuation">(</span><span        class="token punctuation">)</span>MyObject <span class="token operator">=</span> MyClass<span class="token punctuation">(</span><span            class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>你已经知道使用<code>type</code>可以创建类：</p><pre class="line-numbers  language-python"><code class="python  language-python">MyClass <span        class="token operator">=</span> <span class="token builtin">type</span><span        class="token punctuation">(</span><span class="token string">'MyClass'</span><span        class="token punctuation">,</span> <span class="token punctuation">(</span><span        class="token punctuation">)</span><span class="token punctuation">,</span> <span        class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span        class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>那是因为<strong>type</strong>函数实际上就是一个元类，Python使用<strong>type</strong>作为元类来创建所有的类。<br>    通过检查<strong><strong>class</strong></strong>属性，我们可以知道，其实Python中任何数据类型都是对象，包括整型、字符串、函数以及类，它们都是对象。它们都是从类中创建的。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> age <span class="token operator">=</span> <span        class="token number">35</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> age<span class="token punctuation">.</span>__class__<span class="token operator">&lt;</span><span class="token builtin">type</span> <span            class="token string">'int'</span><span class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> name <span            class="token operator">=</span> <span class="token string">'bob'</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> name<span            class="token punctuation">.</span>__class__<span class="token operator">&lt;</span><span class="token builtin">type</span> <span            class="token string">'str'</span><span class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">def</span> <span class="token function">foo</span><span            class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">:</span> <span            class="token keyword">pass</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> foo<span class="token punctuation">.</span>__class__<span class="token operator">&lt;</span><span class="token builtin">type</span> <span            class="token string">'function'</span><span class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">class</span> <span class="token class-name">Bar</span><span            class="token punctuation">(</span><span class="token builtin">object</span><span            class="token punctuation">)</span><span class="token punctuation">:</span> <span            class="token keyword">pass</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> b <span            class="token operator">=</span> Bar<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> b<span            class="token punctuation">.</span>__class__<span class="token operator">&lt;</span><span class="token keyword">class</span> <span class="token string">'__main__.Bar'</span><span            class="token operator">&gt;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>那么<code>__class__</code>的<code>__class__</code>是什么呢？</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> age<span class="token punctuation">.</span>__class__<span        class="token punctuation">.</span>__class__<span class="token operator">&lt;</span><span class="token builtin">type</span> <span class="token string">'type'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> name<span            class="token punctuation">.</span>__class__<span class="token punctuation">.</span>__class__<span class="token operator">&lt;</span><span class="token builtin">type</span> <span class="token string">'type'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> foo<span class="token punctuation">.</span>__class__<span            class="token punctuation">.</span>__class__<span class="token operator">&lt;</span><span class="token builtin">type</span> <span class="token string">'type'</span><span            class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> b<span            class="token punctuation">.</span>__class__<span class="token punctuation">.</span>__class__<span class="token operator">&lt;</span><span class="token builtin">type</span> <span class="token string">'type'</span><span            class="token operator">&gt;</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>所以类其实就是通过元类来创建的，你可以将元类称之为类工厂。<br>    <strong>type</strong>是内置的元类，Python默认使用它来创建类。当然，我们也可以定义属于我们自己的元类。</p><h3>    <strong><strong>metaclass</strong></strong>属性</h3><p>当我们创建类的时候，可以给它添加<strong><strong>metaclass</strong></strong>属性:</p><pre class="line-numbers  language-kotlin"><code class="  language-kotlin"><span        class="token keyword">class</span> <span        class="token function">Foo</span><span class="token punctuation">(</span><span        class="token keyword">object</span><span class="token punctuation">)</span><span        class="token operator">:</span>  __metaclass__ <span class="token operator">=</span> something<span class="token operator">..</span><span            class="token punctuation">.</span>  <span class="token punctuation">[</span><span class="token operator">..</span><span class="token punctuation">.</span><span            class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>如果我们定义了<strong><strong>metaclass</strong></strong>属性，Python就会使用这个元类来创建类Foo。<br>    注意，编译器首先读取<code>class Foo(object)</code>，这时并不会在内存中创建Foo类。Python会继续查找类定义中的<code>__meatclass__</code>，如果找到了，就使用它来创建类Foo，如果没有找到，就使用<strong>type</strong>来创建类。<br>    所以对于以下代码：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">class</span> <span class="token class-name">Foo</span><span        class="token punctuation">(</span>Bar<span        class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token keyword">pass</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>Python工作流程如下：</p><ul>    <li>首先检查<code>Foo</code>中是否具有属性<code>__metaclass__</code>？</li></ul><ul>    <li>如果找到，就使用<code>__metaclass__</code>定义的元类在内存中创建一个类对象。</li></ul><ul>    <li>如果在类定义中没有找到这个属性，就在模块级别中进行查找。</li></ul><ul>    <li>如果还是没有找到，就会使用父类Bar中的元类来创建类。</li></ul><p>注意：类中的<code>__metaclass__</code>属性不会被子类继承，但是父类中的<code>__class__</code>会被继承。</p><h3>自定义元类</h3><p>元类的主要作用是在创建类的时候自动改变类。<br>    例如，想要实现模块中所有的类属性都是大写格式。可以定义模块级别的<code>__metaclass__</code>来实现。<br>    这样模块中所有的类都是通过这个元类来创建的。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">def</span> <span class="token function">upper_attr</span><span        class="token punctuation">(</span>future_class_name<span class="token punctuation">,</span> future_class_parents<span        class="token punctuation">,</span> future_class_attr<span class="token punctuation">)</span><span        class="token punctuation">:</span>  <span class="token triple-quoted-string string">"""    返回一个类，该类的所有属性名的都为大写  """</span>  <span class="token comment"># 将不是__开头的属性名转为大写字母</span>  uppercase_attr <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span            class="token punctuation">&#125;</span>  <span class="token keyword">for</span> name<span class="token punctuation">,</span> val <span            class="token keyword">in</span> future_class_attr<span class="token punctuation">.</span>items<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>      <span class="token keyword">if</span> <span class="token keyword">not</span> name<span            class="token punctuation">.</span>startswith<span class="token punctuation">(</span><span            class="token string">'__'</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>          uppercase_attr<span class="token punctuation">[</span>name<span class="token punctuation">.</span>upper<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">]</span> <span class="token operator">=</span> val      <span class="token keyword">else</span><span class="token punctuation">:</span>          uppercase_attr<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span            class="token operator">=</span> val  <span class="token comment"># 使用type创建类</span>  <span class="token keyword">return</span> <span class="token builtin">type</span><span            class="token punctuation">(</span>future_class_name<span class="token punctuation">,</span> future_class_parents<span            class="token punctuation">,</span> uppercase_attr<span class="token punctuation">)</span><p><strong>metaclass</strong> <span class="token operator">=</span> upper_attr <span            class="token comment"># 定义模块级别的元类，这样模块中所有类都会使用该元类创建</span></p><p><span class="token keyword">class</span> <span class="token class-name">Foo</span><span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span><br>  <span class="token comment"># 注意，新式类不支持模块级别的元类，但是可以在类中定义__metaclass__</span><br>  bar <span class="token operator">=</span> <span class="token string">‘bip’</span></p><p><span class="token keyword">print</span><span class="token punctuation">(</span><span            class="token builtin">hasattr</span><span class="token punctuation">(</span>Foo<span            class="token punctuation">,</span> <span class="token string">‘bar’</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token comment"># 输出: False</span><br><span class="token keyword">print</span><span class="token punctuation">(</span><span            class="token builtin">hasattr</span><span class="token punctuation">(</span>Foo<span            class="token punctuation">,</span> <span class="token string">‘BAR’</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token comment"># 输出: True</span></p><p>f <span class="token operator">=</span> Foo<span class="token punctuation">(</span><span            class="token punctuation">)</span><br><span class="token keyword">print</span><span class="token punctuation">(</span>f<span            class="token punctuation">.</span>BAR<span class="token punctuation">)</span><br><span class="token comment"># Out: ‘bip’</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>也可以将<code>metaclass</code>定义为一个真正的类:</p><pre class="line-numbers  language-python"><code class="python  language-python"><span class="token comment"># 记住type还是一个类，所以可以继承它</span><span class="token keyword">class</span> <span class="token class-name">UpperAttrMetaclass</span><span            class="token punctuation">(</span><span class="token builtin">type</span><span            class="token punctuation">)</span><span class="token punctuation">:</span>     <span class="token comment"># __new__ 会在__init__之前调用，它会创建并返回一个实例</span>    <span class="token comment"># 而__init__仅用于初始化，进行一些参数的配置 </span>    <span class="token keyword">def</span> <span class="token function">__new__</span><span            class="token punctuation">(</span>upperattr_metaclass<span class="token punctuation">,</span> future_class_name<span            class="token punctuation">,</span>                 future_class_parents<span class="token punctuation">,</span> future_class_attr<span            class="token punctuation">)</span><span class="token punctuation">:</span>        uppercase_attr <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span            class="token punctuation">&#125;</span>        <span class="token keyword">for</span> name<span class="token punctuation">,</span> val <span            class="token keyword">in</span> future_class_attr<span class="token punctuation">.</span>items<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>            <span class="token keyword">if</span> <span class="token keyword">not</span> name<span            class="token punctuation">.</span>startswith<span class="token punctuation">(</span><span            class="token string">'__'</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>                uppercase_attr<span class="token punctuation">[</span>name<span            class="token punctuation">.</span>upper<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">]</span> <span            class="token operator">=</span> val            <span class="token keyword">else</span><span class="token punctuation">:</span>                uppercase_attr<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span            class="token operator">=</span> val<pre><code>    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;type&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;future_class_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; future_class_parents&lt;span        class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; uppercase_attr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;</code></pre><p><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>但是上面的做法并不符合OOP的思想，因为它直接调用了<strong>type</strong>方法，实际上可以调用<strong>type</strong>的<code>__new__</code>方法。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">class</span> <span class="token class-name">UpperAttrMetaclass</span><span        class="token punctuation">(</span><span class="token builtin">type</span><span        class="token punctuation">)</span><span class="token punctuation">:</span>     <span class="token keyword">def</span> <span class="token function">__new__</span><span            class="token punctuation">(</span>upperattr_metaclass<span class="token punctuation">,</span> future_class_name<span            class="token punctuation">,</span>                 future_class_parents<span class="token punctuation">,</span> future_class_attr<span            class="token punctuation">)</span><span class="token punctuation">:</span>        uppercase_attr <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span            class="token punctuation">&#125;</span>        <span class="token keyword">for</span> name<span class="token punctuation">,</span> val <span            class="token keyword">in</span> future_class_attr<span class="token punctuation">.</span>items<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>            <span class="token keyword">if</span> <span class="token keyword">not</span> name<span            class="token punctuation">.</span>startswith<span class="token punctuation">(</span><span            class="token string">'__'</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>                uppercase_attr<span class="token punctuation">[</span>name<span            class="token punctuation">.</span>upper<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">]</span> <span            class="token operator">=</span> val            <span class="token keyword">else</span><span class="token punctuation">:</span>                uppercase_attr<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span            class="token operator">=</span> val        <span class="token comment"># 调用type.__new__方法 </span>        <span class="token keyword">return</span> <span class="token builtin">type</span><span            class="token punctuation">.</span>__new__<span            class="token punctuation">(</span>upperattr_metaclass<span class="token punctuation">,</span> future_class_name<span            class="token punctuation">,</span>                             future_class_parents<span class="token punctuation">,</span> uppercase_attr<span            class="token punctuation">)</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>你可能注意到参数<code>upperattr_metaclass</code>, 它代表要实例化的类。当然，我这里取这么个复杂的名字主要是为了明确它的含义。但是，就像<code>self</code>参数一样，所有参数都有其习惯性命名。所以生产环境下的<code>metaclass</code>定义如下：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">class</span> <span class="token class-name">UpperAttrMetaclass</span><span        class="token punctuation">(</span><span class="token builtin">type</span><span        class="token punctuation">)</span><span class="token punctuation">:</span>     <span class="token keyword">def</span> <span class="token function">__new__</span><span            class="token punctuation">(</span>cls<span class="token punctuation">,</span> clsname<span            class="token punctuation">,</span> bases<span class="token punctuation">,</span> dct<span            class="token punctuation">)</span><span class="token punctuation">:</span>        uppercase_attr <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span            class="token punctuation">&#125;</span>        <span class="token keyword">for</span> name<span class="token punctuation">,</span> val <span            class="token keyword">in</span> dct<span class="token punctuation">.</span>items<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>            <span class="token keyword">if</span> <span class="token keyword">not</span> name<span            class="token punctuation">.</span>startswith<span class="token punctuation">(</span><span            class="token string">'__'</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>                uppercase_attr<span class="token punctuation">[</span>name<span            class="token punctuation">.</span>upper<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">]</span> <span            class="token operator">=</span> val            <span class="token keyword">else</span><span class="token punctuation">:</span>                uppercase_attr<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span            class="token operator">=</span> val        <span class="token keyword">return</span> <span class="token builtin">type</span><span            class="token punctuation">.</span>__new__<span class="token punctuation">(</span>cls<span            class="token punctuation">,</span> clsname<span class="token punctuation">,</span> bases<span            class="token punctuation">,</span> uppercase_attr<span class="token punctuation">)</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>更好的方式是使用<code>super</code>方法，以便减轻这种继承关系。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">class</span> <span class="token class-name">UpperAttrMetaclass</span><span        class="token punctuation">(</span><span class="token builtin">type</span><span        class="token punctuation">)</span><span class="token punctuation">:</span>     <span class="token keyword">def</span> <span class="token function">__new__</span><span            class="token punctuation">(</span>cls<span class="token punctuation">,</span> clsname<span            class="token punctuation">,</span> bases<span class="token punctuation">,</span> dct<span            class="token punctuation">)</span><span class="token punctuation">:</span>        uppercase_attr <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span            class="token punctuation">&#125;</span>        <span class="token keyword">for</span> name<span class="token punctuation">,</span> val <span            class="token keyword">in</span> dct<span class="token punctuation">.</span>items<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>            <span class="token keyword">if</span> <span class="token keyword">not</span> name<span            class="token punctuation">.</span>startswith<span class="token punctuation">(</span><span            class="token string">'__'</span><span class="token punctuation">)</span><span            class="token punctuation">:</span>                uppercase_attr<span class="token punctuation">[</span>name<span            class="token punctuation">.</span>upper<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">]</span> <span            class="token operator">=</span> val            <span class="token keyword">else</span><span class="token punctuation">:</span>                uppercase_attr<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span            class="token operator">=</span> val<pre><code>    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;super&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UpperAttrMetaclass&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cls&lt;span        class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__new__&lt;span        class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cls&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; clsname&lt;span        class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bases&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; uppercase_attr&lt;span        class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;</code></pre><p><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>元类实际上做了以下三方面的工作：</p><ul>    <li>干涉创建类的过程</li>    <li>修改类</li>    <li>返回修改之后的类</li></ul><h3>为什么使用类而不是函数来定义元类？</h3><p>理由如下：</p><ul>    <li>目的更明确，当你阅读<code>UpperAttrMetaclass(type)</code>的时候，你知道它用来做什么。</li>    <li>可以使用面向对象编程，元类可以继承自其它元类，还可以覆盖父类方法。</li>    <li>可以更好的组织代码结构。元类通常用于处理比较复杂的情况。</li>    <li>可以为<code>__new__</code>、<code>__init__</code>和<code>__call__</code>编写钩子，为后续开发者提供便利。</li></ul><h3>为什么使用元类？</h3><p>现在，终极问题来了，为什么要使用元类这种模糊且容易出错的功能？<br>    一般情况下，我们并不会使用元类，99%的开发者并不会用到元类，所以一般不用考虑这个问题。<br>    元类主用用于创建API，一个典型的例子就是Django的ORM。<br>    它让我们可以这样定义一个类：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">class</span> <span class="token class-name">Person</span><span        class="token punctuation">(</span>models<span class="token punctuation">.</span>Model<span        class="token punctuation">)</span><span class="token punctuation">:</span>  name <span class="token operator">=</span> models<span class="token punctuation">.</span>CharField<span            class="token punctuation">(</span>max_length<span class="token operator">=</span><span            class="token number">30</span><span class="token punctuation">)</span>  age <span class="token operator">=</span> models<span class="token punctuation">.</span>IntegerField<span            class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>运行下面的代码：</p><pre class="line-numbers  language-python"><code class="python  language-python">guy <span        class="token operator">=</span> Person<span class="token punctuation">(</span>name<span        class="token operator">=</span><span class="token string">'bob'</span><span        class="token punctuation">,</span> age<span class="token operator">=</span><span        class="token string">'35'</span><span class="token punctuation">)</span><span class="token keyword">print</span><span class="token punctuation">(</span>guy<span            class="token punctuation">.</span>age<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code><button class="VJbwyy"                                                                                                   type="button"                                                                                                   aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>    返回的结果是<code>int</code>类型而不是<code>IntegerField</code>对象。这是因为<code>models.Model</code>使用了元类，它会将Python中定义的字段转换成数据库中的字段。<br>    通过使用元类，Django将复杂的接口转换成简单的接口。</p><h3>总结</h3><p>首先，我们知道了类其实就是可以创建实例的对象。而类又是通过元类来创建的。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">class</span> <span        class="token class-name">Foo</span><span        class="token punctuation">(</span><span class="token builtin">object</span><span        class="token punctuation">)</span><span class="token punctuation">:</span> <span        class="token keyword">pass</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token builtin">id</span><span class="token punctuation">(</span>Foo<span            class="token punctuation">)</span><span class="token number">142630324</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>Python中所有数据类型都是对象，它们要么是类的实例要么是元类的实例。<br>    除了<strong>type</strong>，它实际上是自身的元类。这一点没法在Python中重现，因为它是在编译阶段实现的。</p><p>其次， 元类都是复杂的，对于一般的类是用不着的。可以使用以下两种技巧修改类：</p><ul>    <li>monkey patch</li>    <li>类修饰器</li></ul><p>当你需要修改类的时候，99%的情况下可以使用元类。但是99%的情况下，你根本不需要修改一个类。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中read(),readline(),readlines()区别与用法</title>
      <link href="cp/python/python-read-about/"/>
      <url>cp/python/python-read-about/</url>
      
        <content type="html"><![CDATA[<h2>整理一下python3里面关于read、readline、readlines的方法，有关文件打开模式的内容可以参见我之前的文章</h2><blockquote>    <p>文件 runoob.txt 的内容如下：</p></blockquote><pre class="line-numbers  language-css"><code class="  language-css">1<span class="token punctuation">:</span>www.runoob.com2<span class="token punctuation">:</span>www.runoob.com3<span class="token punctuation">:</span>www.runoob.com4<span class="token punctuation">:</span>www.runoob.com5<span class="token punctuation">:</span>www.runoob.com<span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><h2>1. read方法</h2><h3>概述</h3><p>read() 方法用于从文件读取指定的字节数，如果未给定或为负则读取所有。</p><h3>语法</h3><blockquote>    <p>read() 方法语法如下：</p></blockquote><pre class="line-numbers  language-css"><code class="  language-css">fileObject.<span        class="token function">read</span><span class="token punctuation">(</span><span        class="token punctuation">)</span><span class="token punctuation">;</span> <span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><h3>参数</h3><p>size -- 从文件中读取的字节数。若无size参数则默认读取全部</p><h3>返回值</h3><p>返回从字符串中读取的字节。</p><h3>实例</h3><pre class="line-numbers  language-bash"><code class="  language-bash">#!/usr/bin/python# -*- coding: UTF-8 -*-<h1 id="打开文件"><a href="#打开文件" class="headerlink" title="打开文件"></a>打开文件</h1><p>fo = open(“runoob.txt”, “rw+”)<br>print “文件名为: “, fo.name</p><p>line = fo.read(10)<br>print “读取的字符串: %s” % (line)</p><h1 id="关闭文件"><a href="#关闭文件" class="headerlink" title="关闭文件"></a>关闭文件</h1><p>fo.close()</p><p>#输出<br>文件名为:  runoob.txt<br>读取的字符串: 1:<a href="http://www.runo/">www.runo</a><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><h2>2. readline</h2><h3>概述</h3><p>readline() 方法用于从文件读取整行，包括 "\n" 字符。如果指定了一个非负数的参数，则返回指定大小的字节数，包括 "\n"    字符。因为每次仅读取一行，所以读取时占用内存小，比较适合大文件，该方法返回一个字符串对象。</p><h3>语法</h3><blockquote>    <p>readline() 方法语法如下：</p></blockquote><pre class="line-numbers  language-css"><code class="  language-css">fileObject.<span        class="token function">readline</span><span        class="token punctuation">(</span><span class="token punctuation">)</span><span        class="token punctuation">;</span> <span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><h3>参数</h3><p>size -- 从文件中读取的字节数。</p><h3>返回值</h3><p>返回从字符串中读取的字节。</p><h3>实例</h3><pre class="line-numbers  language-bash"><code class="  language-bash">#!/usr/bin/python# -*- coding: UTF-8 -*-<h1 id="打开文件-1"><a href="#打开文件-1" class="headerlink" title="打开文件"></a>打开文件</h1><p>fo = open(“runoob.txt”, “rw+”)<br>print “文件名为: “, fo.name</p><p>line = fo.readline()<br>print “读取第一行 %s” % (line)</p><p>line = fo.readline(5)<br>print “读取的字符串为: %s” % (line)</p><h1 id="关闭文件-1"><a href="#关闭文件-1" class="headerlink" title="关闭文件"></a>关闭文件</h1><p>fo.close()</p><p>#输出<br>文件名为:  runoob.txt<br>读取第一行 1:<a href="http://www.runoob.com/">www.runoob.com</a></p><p>读取的字符串为: 2:www<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><h2>3. readlines</h2><h3>概述</h3><p>readlines() 方法用于读取所有行(直到结束符 EOF)并返回列表，每行作为一个元素，该列表可以由 Python 的 for... in ... 结构进行处理。但读取大文件会比较占内存。</p><ul>    <li>如果碰到结束符 EOF 则返回空字符串。</li></ul><h3>语法</h3><blockquote>    <p>readlines() 方法语法如下：</p></blockquote><pre class="line-numbers  language-css"><code class="  language-css">fileObject.<span        class="token function">readlines</span><span        class="token punctuation">(</span> <span class="token punctuation">)</span><span        class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code><button class="VJbwyy" type="button"                                                                                      aria-label="复制代码"><i        aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" focusable="false" class=""                                                                  data-icon="copy" width="1em" height="1em"                                                                  fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><h3>参数</h3><p>无。</p><h3>返回值</h3><p>返回列表，包含所有的行。</p><h3>实例</h3><pre class="line-numbers  language-ruby"><code class="  language-ruby"><span        class="token comment">#!/usr/bin/python</span><span class="token comment"># -*- coding: UTF-8 -*-</span> <span class="token comment"># 打开文件</span>fo <span class="token operator">=</span> open<span class="token punctuation">(</span><span class="token string">"runoob.txt"</span><span            class="token punctuation">,</span> <span class="token string">"r"</span><span            class="token punctuation">)</span>print <span class="token string">"文件名为: "</span><span class="token punctuation">,</span> fo<span            class="token punctuation">.</span>name <span class="token keyword">for</span> line <span class="token keyword">in</span> fo<span            class="token punctuation">.</span>readlines<span class="token punctuation">(</span><span            class="token punctuation">)</span><span            class="token punctuation">:</span>                          <span class="token comment">#依次读取每行  </span>    line <span class="token operator">=</span> line<span class="token punctuation">.</span>strip<span            class="token punctuation">(</span><span            class="token punctuation">)</span>                             <span            class="token comment">#去掉每行头尾空白  </span>    print <span class="token string">"读取的数据为: %s"</span> <span class="token operator">%</span> <span            class="token punctuation">(</span>line<span class="token punctuation">)</span> <span class="token comment"># 关闭文件</span>fo<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span            class="token punctuation">)</span><p><span class="token comment">#输出</span><br>文件名为<span class="token punctuation">:</span>  runoob<span class="token punctuation">.</span>txt<br>读取的数据为<span class="token punctuation">:</span> <span class="token number">1</span><span class="token symbol">:www</span><span            class="token punctuation">.</span>runoob<span class="token punctuation">.</span>com<br>读取的数据为<span class="token punctuation">:</span> <span class="token number">2</span><span class="token symbol">:www</span><span            class="token punctuation">.</span>runoob<span class="token punctuation">.</span>com<br>读取的数据为<span class="token punctuation">:</span> <span class="token number">3</span><span class="token symbol">:www</span><span            class="token punctuation">.</span>runoob<span class="token punctuation">.</span>com<br>读取的数据为<span class="token punctuation">:</span> <span class="token number">4</span><span class="token symbol">:www</span><span            class="token punctuation">.</span>runoob<span class="token punctuation">.</span>com<br>读取的数据为<span class="token punctuation">:</span> <span class="token number">5</span><span class="token symbol">:www</span><span            class="token punctuation">.</span>runoob<span class="token punctuation">.</span>com<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><h2>4. linecache模块</h2><blockquote>    <p>当然，有特殊需求还可以用linecache模块，比如你要输出某个文件的第n行：</p></blockquote><pre class="line-numbers  language-bash"><code class="  language-bash"># 输出第2行text = linecache.getline(‘a.txt’,2)print text<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><ul>    <li>处理大文件也比较有效率</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python 最常见的 170 道面试题全解析：2019 版(题目列表)</title>
      <link href="cp/python/python-interview/"/>
      <url>cp/python/python-interview/</url>
      
        <content type="html"><![CDATA[<div class="rich_media_content" id="js_content">    <h3 style="color:inherit;line-height:inherit;font-weight:bold;border-bottom:2px solid rgb(239,112,96);font-size:1.3em;">        <a name="t0"></a><span            style="font-size:inherit;line-height:inherit;font-weight:normal;background:rgb(239,112,96);color:rgb(255,255,255);">引言</span><span            style="vertical-align:bottom;border-bottom:36px solid rgb(239,235,233);border-right:20px solid transparent;"> </span>    </h3>    <p style="font-size:inherit;color:inherit;line-height:inherit;">最近在刷面试题,所以需要看大量的 Python        相关的面试题，从大量的题目中总结了很多的知识，同时也对一些题目进行拓展了，但是在看了网上的大部分面试题不是很满意，一个是有些部分还是 Python2        的代码，另一个就是回答的很简单，有些关键的题目，也没有点出为什么，最重要的是还有一些复制粘贴根本就跑不通，这种相信大家深有体会吧，这样就导致我们可能需要去找其他人发的类似的教程。难受啊，所以我决定针对市面上大多的        Python 题目做一个分析，同时也希望大家尽可能的做到举一反三，而不是局限于题目本身。大概就这样吧，有你看过的题目也有你没看到过的。</p>    <h3 style="color:inherit;line-height:inherit;font-weight:bold;border-bottom:2px solid rgb(239,112,96);font-size:1.3em;">        <a name="t1"></a><span            style="font-size:inherit;line-height:inherit;font-weight:normal;background:rgb(239,112,96);color:rgb(255,255,255);">通过本场 Chat，你将获得如下知识点：</span><span            style="vertical-align:bottom;border-bottom:36px solid rgb(239,235,233);border-right:20px solid transparent;"> </span>    </h3>    <ul style="margin-left:16px;" class="list-paddingleft-2">        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">掌握 Python 的基础语法</span></p></li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">语法常见的 Python 应用场景</span></p></li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">掌握 Python 闭包的使用以及装饰器的使用</span></p>        </li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">生成器和迭代器的使用</span></p></li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">常见的设计模式的使用</span></p></li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">深浅拷贝的区别</span></p></li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">线程、进程、协程的使用</span></p></li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">了解 Python 中的元编程和反射</span></p></li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">常考的数据结构和算法</span></p></li>        <li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">爬虫相关知识，网络编程基本知识等</span></p></li>    </ul>    <h3 style="color:inherit;line-height:inherit;font-weight:bold;border-bottom:2px solid rgb(239,112,96);font-size:1.3em;">        <a name="t2"></a><span            style="font-size:inherit;line-height:inherit;font-weight:normal;background:rgb(239,112,96);color:rgb(255,255,255);">所有题目</span><span            style="vertical-align:bottom;border-bottom:36px solid rgb(239,235,233);border-right:20px solid transparent;"> </span>    </h3><h4 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">语言特性</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">1.谈谈对 Python 和其他语言的区别<br>2.简述解释型和编译型编程语言<br>3.Python        的解释器种类以及相关特点？<br>4.说说你知道的Python3 和 Python2 之间的区别？<br>5.Python3 和 Python2 中 int 和 long 区别？<br>6.xrange 和 range        的区别？</p><h4 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">编码规范</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">7.什么是 PEP8?<br>8.了解 Python 之禅么？<br>9.了解 dosctring 么？<br>10.了解类型注解么？<br>11.例举你知道        Python 对象的命名规范，例如方法或者类等<br>12.Python 中的注释有几种？<br>13.如何优雅的给一个函数加注释？<br>14.如何给变量加注释？<br>15.Python 代码缩进中是否支持 Tab        键和空格混用。<br>16.是否可以在一句 import 中导入多个库?<br>17.在给 Py 文件命名的时候需要注意什么?<br>18.例举几个规范 Python 代码风格的工具</p><h4        style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">数据类型</span></h4><h5        style="color:inherit;line-height:inherit;font-weight:bold;font-size:1em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">字符串</span></h5>    <p style="font-size:inherit;color:inherit;line-height:inherit;">19.列举 Python 中的基本数据类型？<br>20.如何区别可变数据类型和不可变数据类型<br>21.将"hello        world"转换为首字母大写"Hello World"<br>22.如何检测字符串中只含有数字?<br>23.将字符串"ilovechina"进行反转<br>24.Python 中的字符串格式化方式你知道哪些？<br>25.有一个字符串开头和末尾都有空格，比如“        adabdw ”,要求写一个函数把这个字符串的前后空格都去掉。<br>26.获取字符串”123456“最后的两个字符。<br>27.一个编码为 GBK 的字符串 S，要将其转成 UTF-8 编码的字符串，应如何操作？<br>28.s="info:xiaoZhang        33 shandong",用正则切分字符串输出['info', 'xiaoZhang', '33', 'shandong']<br>27.怎样将字符串转换为小写？<br>28.单引号、双引号、三引号的区别？<br>29.a        = "你好 &nbsp; &nbsp; 中国 &nbsp;",去除多余空格只留一个空格。</p><h5        style="color:inherit;line-height:inherit;font-weight:bold;font-size:1em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">列表</span></h5>    <p style="font-size:inherit;color:inherit;line-height:inherit;">30.已知 AList = [1,2,3,1,2],对 AList 列表元素去重，写出具体过程。<br>31.如何实现        "1,2,3" 变成 ["1","2","3"]<br>32.给定两个 list，A 和        B，找出相同元素和不同元素<br>33.[[1,2],[3,4],[5,6]]一行代码展开该列表，得出[1,2,3,4,5,6]<br>34.合并列表[1,5,7,9]和[2,2,6,8]<br>35.如何打乱一个列表的元素？    </p><h5 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">字典</span></h5>    <p style="font-size:inherit;color:inherit;line-height:inherit;">36.字典操作中 del 和 pop 有什么区别<br>37.按照字典的内的年龄排序</p>    <pre><code class="hljs"></code><div class="hljs-button {2}" data-title="复制"                                        onclick="hljs.copyCode(event)"></div></pre>    <p style="font-size:inherit;color:inherit;line-height:inherit;">38.请合并下面两个字典 a = {"A":1,"B":2},b = {"C":3,"D":4}<br>39.如何使用生成式的方式生成一个字典，写一段功能代码。<br>40.如何把元组("a","b")和元组(1,2)，变为字典{"a":1,"b":2}    </p><h5 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">综合</span></h5>    <p style="font-size:inherit;color:inherit;line-height:inherit;">41.Python 常用的数据结构的类型及其特性？</p>    <pre style="font-size:inherit;color:inherit;line-height:inherit;"></pre>    <p style="line-height:18px;font-size:14px;word-spacing:0px;letter-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);background:rgb(40,43,46);margin-left:16px;">        <span class="hljs-section"              style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">A：{1:0,2:0,3:0}</span><br><span            class="hljs-section" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">B：{"a":0,&nbsp;"b":0,&nbsp;"c":0}</span><br><span            class="hljs-section" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">C:&nbsp;{(1,2):0,&nbsp;(2,3):0}</span><br><span            class="hljs-section" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">D:&nbsp;{[1,2]:0,&nbsp;[2,3]:0}</span><br>    </p>    <p style="font-size:inherit;color:inherit;line-height:inherit;">42.如何将元组("A","B")和元组(1,2),合并成字典{"A":1,"B":2}<br>43.Python        里面如何实现 tuple 和 list 的转换？<br>44.我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？<br>45.请将[i for i in        range(3)]改成生成器<br>46.a="hello"和 b="你好"编码成 bytes 类型<br>47.下面的代码输出结果是什么？</p>    <pre style="font-size:inherit;color:inherit;line-height:inherit;"></pre>    <p style="line-height:18px;font-size:14px;word-spacing:0px;letter-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);background:rgb(40,43,46);margin-left:16px;">        <span class="hljs-attr" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">a</span>&nbsp;=&nbsp;(<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">1</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">2</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">3</span>,[<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">4</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">5</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">6</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">7</span>],<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">8</span>)<br><span            class="hljs-attr" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">a[2]</span>&nbsp;=&nbsp;<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">2</span><br></p>    <p style="font-size:inherit;color:inherit;line-height:inherit;">48.下面的代码输出的结果是什么?</p>    <pre style="font-size:inherit;color:inherit;line-height:inherit;"></pre>    <p style="line-height:18px;font-size:14px;word-spacing:0px;letter-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);background:rgb(40,43,46);margin-left:16px;">        <span class="hljs-attr" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">a</span>&nbsp;=&nbsp;(<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">1</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">2</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">3</span>,[<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">4</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">5</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">6</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">7</span>],<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">8</span>)<br><span            class="hljs-attr" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">a[5]</span>&nbsp;=&nbsp;<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">2</span><br></p>    <h4 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span            style="font-size:inherit;color:inherit;line-height:inherit;">操作类题目</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">49.Python 交换两个变量的值<br>50.在读文件操作的时候会使用 read、readline        或者 readlines，简述它们各自的左右<br>51.json 序列化时，可以处理的数据类型有哪些？如何定制支持 datetime 类型？<br>52.json 序列化时，默认遇到中文会转换成        unicode，如果想要保留中文怎么办？<br>53.有两个磁盘文件 A 和 B，各存放一行字母，要求把这两个文件中的信息合并(按字母顺序排列)，输出到一个新文件 C 中。<br>54.如果当前的日期为        20190530，要求写一个函数输出 N 天后的日期，(比如 N 为 2，则输出 20190601)。<br>55.写一个函数，接收整数参数 n，返回一个函数，函数的功能是把函数的参数和 n 相乘并把结果返回。<br>56.下面代码会存在什么问题，如何改进？    </p>    <pre style="font-size:inherit;color:inherit;line-height:inherit;"></pre>    <p style="line-height:18px;font-size:14px;word-spacing:0px;letter-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);background:rgb(40,43,46);margin-left:16px;">        <span class="hljs-function" style="font-size:inherit;line-height:inherit;color:rgb(248,35,117);"><span                class="hljs-keyword" style="font-size:inherit;line-height:inherit;">def</span>&nbsp;<span                class="hljs-title" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">strappend</span><span                class="hljs-params"                style="font-size:inherit;line-height:inherit;color:rgb(255,152,35);">(num)</span>:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;str=<span            class="hljs-string" style="font-size:inherit;line-height:inherit;color:rgb(238,220,112);">'first'</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span            class="hljs-keyword" style="font-size:inherit;line-height:inherit;color:rgb(248,35,117);">for</span>&nbsp;i&nbsp;<span            class="hljs-keyword" style="font-size:inherit;line-height:inherit;color:rgb(248,35,117);">in</span>&nbsp;range(num):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str+=str(i)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span            class="hljs-keyword" style="font-size:inherit;line-height:inherit;color:rgb(248,35,117);">return</span>&nbsp;str<br>    </p>    <p style="font-size:inherit;color:inherit;line-height:inherit;">57.一行代码输出 1-100 之间的所有偶数。<br>58.with 语句的作用，写一段代码？<br>59.python        字典和 json 字符串相互转化方法<br>60.请写一个 Python 逻辑，计算一个文件中的大写字母数量</p><h4        style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">高级特性</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">70.函数装饰器有什么作用？请列举说明？<br>71.Python 垃圾回收机制？<br>72.魔法函数        __call__怎么使用?<br>73.如何判断一个对象是函数还是方法？<br>74.@classmethod 和@staticmethod 用法和区别<br>75.Python 中的接口如何实现？<br>76.Python        中的反射了解么?<br>77.metaclass 作用？以及应用场景？<br>78.hasattr() getattr() setattr()的用法<br>79.请列举你知道的 Python 的魔法方法及用途。<br>80.如何知道一个        Python 对象的类型？<br>81.Python 的传参是传值还是传址？<br>82.Python 中的元类(metaclass)使用举例<br>83.简述 any()和 all()方法<br>84.filter        方法求出列表所有奇数并构造新列表，a = &nbsp;[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]<br>85.什么是猴子补丁？<br>86.在 Python 中是如何管理内存的？<br>87.当退出        Python 时是否释放所有内存分配？</p><h4 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">正则表达式</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">88.使用正则表达式匹配出&lt;html&gt;&lt;h1&gt;www.baidu.com&lt;/html&gt;中的地址<br>a="张明        98 分"，用 re.sub，将 98 替换为 100<br>89.正则表达式匹配中(.*)和(.*?)匹配区别？<br>90.写一段匹配邮箱的正则表达式</p><h4        style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">其他内容</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">91.解释一下 python 中 pass 语句的作用？<br>92.简述你对 input()函数的理解<br>93.python        中的 is 和==<br>94.Python 中的作用域<br>95.三元运算写法和应用场景？<br>96.了解 enumerate 么？<br>97.列举 5 个 Python 中的标准模块<br>98.如何在函数中设置一个全局变量<br>99.pathlib        的用法举例<br>100.Python 中的异常处理，写一个简单的应用场景<br>101.Python 中递归的最大次数，那如何突破呢？<br>102.什么是面向对象的 mro<br>103.isinstance        作用以及应用场景？<br>104.什么是断言？应用场景？<br>105.lambda 表达式格式以及应用场景？<br>106.新式类和旧式类的区别<br>107.dir()是干什么用的？<br>108.一个包里有三个模块，demo1.py,        demo2.py, demo3.py，但使用 from tools import *导入模块时，如何保证只有 demo1、demo3 被导入了。<br>109.列举 5 个 Python 中的异常类型以及其含义<br>110.copy        和 deepcopy 的区别是什么？<br>111.代码中经常遇到的*args, **kwargs 含义及用法。<br>112.Python        中会有函数或成员变量包含单下划线前缀和结尾，和双下划线前缀结尾，区别是什么?<br>113.w、a+、wb 文件写入模式的区别<br>114.举例 sort 和 sorted 的区别<br>115.什么是负索引？<br>116.pprint        模块是干什么的？<br>117.解释一下 Python 中的赋值运算符<br>118.解释一下 Python 中的逻辑运算符<br>119.讲讲 Python 中的位运算符<br>120.在 Python        中如何使用多进制数字？<br>121.怎样声明多个变量并赋值？</p><h4        style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">算法和数据结构</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">122.已知：</p>    <pre style="font-size:inherit;color:inherit;line-height:inherit;"></pre>    <p style="line-height:18px;font-size:14px;word-spacing:0px;letter-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);background:rgb(40,43,46);margin-left:16px;">        <span class="hljs-attr" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">AList</span>&nbsp;=&nbsp;[<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">1</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">2</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">3</span>]<br><span            class="hljs-attr" style="font-size:inherit;line-height:inherit;color:rgb(165,218,45);">BSet</span>&nbsp;=&nbsp;{<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">1</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">2</span>,<span            class="hljs-number" style="font-size:inherit;line-height:inherit;color:rgb(174,135,250);">3</span>}<br></p>    <p style="font-size:inherit;color:inherit;line-height:inherit;">(1) 从 AList 和 BSet 中 查找 4，最坏时间复杂度那个大？<br>(2) 从 AList        和 BSet 中 插入 4，最坏时间复杂度那个大？<br>123.用 Python 实现一个二分查找的函数<br>124.python 单例模式的实现方法<br>125.使用 Python 实现一个斐波那契数列<br>126.找出列表中的重复数字<br>127.找出列表中的单个数字<br>128.写一个冒泡排序<br>129.写一个快速排序<br>130.写一个拓扑排序<br>131.python        实现一个二进制计算<br>132.有一组“+”和“-”符号，要求将“+”排到左边，“-”排到右边，写出具体的实现方法。<br>133.单链表反转<br>134.交叉链表求交点<br>135.用队列实现栈<br>136.找出数据流的中位数<br>137.二叉搜索树中第        K 小的元素</p><h4 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">爬虫相关</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">138.在 requests 模块中，requests.content 和 requests.text        什么区别<br>139.简要写一下 lxml 模块的使用方法框架<br>140.说一说 scrapy 的工作流程<br>141.scrapy 的去重原理<br>142.scrapy 中间件有几种类，你用过哪些中间件<br>143.你写爬虫的时候都遇到过什么？反爬虫措施，你是怎么解决的？<br>144.为什么会用到代理？<br>145.代理失效了怎么处理？<br>146.列出你知道        header 的内容以及信息<br>147.说一说打开浏览器访问 www.baidu.com 获取到结果，整个流程。<br>148.爬取速度过快出现了验证码怎么处理<br>149.scrapy 和 scrapy-redis        有什么区别？为什么选择 redis 数据库？<br>150.分布式爬虫主要解决什么问题<br>151.写爬虫是用多进程好？还是多线程好？ 为什么？<br>152.解析网页的解析器使用最多的是哪几个<br>153.需要登录的网页，如何解决同时限制        ip，cookie,session（其中有一些是动态生成的）在不使用动态爬取的情况下？<br>154.验证码的解决（简单的：对图像做处理后可以得到的，困难的：验证码是点击，拖动等动态进行的？）<br>155.使用最多的数据库（mysql，mongodb，redis        等），对他的理解？</p><h4 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">网络编程</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">156.TCP 和 UDP 的区别？<br>157.简要介绍三次握手和四次挥手<br>158.什么是粘包？        socket 中造成粘包的原因是什么？ 哪些情况会发生粘包现象？</p><h4        style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">并发</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">159.举例说明 conccurent.future 的中线程池的用法<br>160.说一说多线程，多进程和协程的区别。<br>161.简述        GIL<br>162.进程之间如何通信<br>163.IO 多路复用的作用？<br>164.select、poll、epoll 模型的区别？<br>165.什么是并发和并行？<br>167.解释什么是异步非阻塞？<br>168.threading.local        的作用？</p><h4 style="color:inherit;line-height:inherit;font-weight:bold;font-size:1.2em;"><span        style="font-size:inherit;color:inherit;line-height:inherit;">Git 面试题</span></h4>    <p style="font-size:inherit;color:inherit;line-height:inherit;">169.说说你知道的 git 命令<br>170.git 如何查看某次提交修改的内容x</p>    <p style="font-size:inherit;color:inherit;text-align:center;line-height:normal;letter-spacing:1px;"><br></p>    <p style="text-align:center;line-height:1.75em;margin-left:16px;"><span style="color:rgb(255,255,255);"><strong>扫描二维码即可看答案</strong></span>    </p>    <p style="text-align:center;line-height:1.75em;margin-left:16px;"><span style="color:rgb(255,255,255);"><strong>限时只要 9.9 元</strong></span>    </p>    <p style="text-align:center;line-height:1.75em;margin-left:16px;"><span style="color:rgb(255,255,255);"><strong>用一杯奶茶钱</strong></span>    </p>    <p style="text-align:center;line-height:1.75em;margin-left:16px;"><span style="color:rgb(255,255,255);"><strong>换取一份 0ffer，</strong><strong>值！</strong></span>    </p>    <p style="text-align:center;line-height:1.75em;margin-left:16px;"><span            style="color:rgb(255,255,255);"><strong>?<strong            style="color:rgb(255,255,255);font-family:'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;font-size:15px;letter-spacing:2px;text-align:center;word-spacing:2px;">?</strong><strong            style="color:rgb(255,255,255);font-family:'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;font-size:15px;letter-spacing:2px;text-align:center;word-spacing:2px;">?</strong></strong></span>    </p>    <p style="text-align:center;"><img class="rich_pages" style="width:350px;"                                       src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_jpg/0vU1ia3htaaMiaMtvkvZ6DUk5sTjoFgaicJoHhoT59peP1M4ibAwbp3qlMEoQJ0gK2ORS4RhG3xhmO6bpJn0JPqhJg/640?wx_fmt=jpeg"                                       alt="640?wx_fmt=jpeg"></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python 最常见的 170 道面试题全解析：2019 版(答案收集)</title>
      <link href="cp/python/python-interview2/"/>
      <url>cp/python/python-interview2/</url>
      
        <content type="html"><![CDATA[<h2 id="语言特性"><a href="#语言特性" class="headerlink" title="语言特性"></a>语言特性</h2><h3 id="1-谈谈对-Python-和其他语言的区别"><a href="#1-谈谈对-Python-和其他语言的区别" class="headerlink" title="1.谈谈对 Python 和其他语言的区别:"></a>1.谈谈对 Python 和其他语言的区别:</h3><p>答：Python 是一门语法简洁优美,功能强大无比,应用领域非常广泛,具有强大完备的第三方库，他是一门强类型的可移植、可扩展，可嵌入的解释型编程语言，属于动态语言。</p><p>拿 C 语言和 Python 比： Python 的第三方类库比较齐全并且使用简洁,很少代码就能实现一些功能，如果用 C 去实现相同的功能可能就比较复杂。</p><p>但是对于速度来说 Python 的运行速度相较于 C 就比较慢了。</p><p>所以有利的同时也有弊端，毕竟我们的学习成本降低了。</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-feature/">详情</a></p><h3 id="2-简述解释型和编译型编程语言"><a href="#2-简述解释型和编译型编程语言" class="headerlink" title="2.简述解释型和编译型编程语言:"></a>2.简述解释型和编译型编程语言:</h3><p>解释型语言是在运行程序的时候才翻译，每执行一行，要翻译一行，边翻译边执行，效率较低。 </p><p>编译型就是直接编译成机型可以执行的，只翻译一次，所以效率相对来说较高。</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/compile-explain/">详情</a></p><h3 id="3-Python-的解释器种类以及相关特点？"><a href="#3-Python-的解释器种类以及相关特点？" class="headerlink" title="3.Python 的解释器种类以及相关特点？"></a>3.Python 的解释器种类以及相关特点？</h3><p>CPython c 语言开发的，使用最广的解释器</p><p>IPython 基于 cPython 之上的一个交互式计时器，交互方式增强功能和 cPython 一样</p><p>PyPy 目标是执行效率，采用 JIT 技术。对 Python 代码进行动态编译，提高执行效率</p><p>JPython 运行在 Java 上的解释器，直接把 Python 代码编译成 Java 字节码执行</p><p>IronPython 运行在微软 .NET 平台上的解释器，把 Python 编译成 . NET 的字节码。</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/interpreter-type/">详情</a></p><h3 id="4-说说你知道的Python3-和-Python2-之间的区别？"><a href="#4-说说你知道的Python3-和-Python2-之间的区别？" class="headerlink" title="4.说说你知道的Python3 和 Python2 之间的区别？"></a>4.说说你知道的Python3 和 Python2 之间的区别？</h3><p>print 在 Python3 中是函数必须加括号，Python2 中 print 为 class。</p><p>Python2 中使用 xrange，Python3 使用 range。</p><p>Python2 中默认的字符串类型默认是 ASCII，Python3 中默认的字符串类型是 Unicode。</p><p>Python2 中/的结果是整型，Python3 中是浮点类型。</p><p>Python2 中声明元类：metaclass = MetaClass,Python3 中声明元类：class newclass(metaclass=MetaClass)：pass。</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python2-python3/">详情</a></p><h3 id="5-Python3-和-Python2-中-int-和-long-区别？"><a href="#5-Python3-和-Python2-中-int-和-long-区别？" class="headerlink" title="5.Python3 和 Python2 中 int 和 long 区别？"></a>5.Python3 和 Python2 中 int 和 long 区别？</h3><p>python2中有int(整数)和long(长整数) 如果你想将int转为long可以在数据末尾加L</p><p>在python3中只有int(整数)</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python23-long/">详情</a></p><h3 id="6-xrange-和-range-的区别？"><a href="#6-xrange-和-range-的区别？" class="headerlink" title="6.xrange 和 range 的区别？"></a>6.xrange 和 range 的区别？</h3><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-range-xrange/">详情</a></p><h2 id="编码规范"><a href="#编码规范" class="headerlink" title="编码规范"></a>编码规范</h2><h3 id="7-什么是-PEP8"><a href="#7-什么是-PEP8" class="headerlink" title="7.什么是 PEP8?"></a>7.什么是 PEP8?</h3><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-pep8/">详情</a></p><h3 id="8-了解-Python-之禅么？"><a href="#8-了解-Python-之禅么？" class="headerlink" title="8.了解 Python 之禅么？"></a>8.了解 Python 之禅么？</h3><p>通过 import this 语句可以获取其具体的内容。告诉人们如何高效整洁的编写代码</p><p>Python之禅 by Tim Peters</p><p>优美胜于丑陋（Python 以编写优美的代码为目标）<br>明了胜于晦涩（优美的代码应当是明了的，命名规范，风格相似）<br>简洁胜于复杂（优美的代码应当是简洁的，不要有复杂的内部实现）<br>复杂胜于凌乱（如果复杂不可避免，那代码间也不能有难懂的关系，要保持接口简洁）<br>扁平胜于嵌套（优美的代码应当是扁平的，不能有太多的嵌套）<br>间隔胜于紧凑（优美的代码有适当的间隔，不要奢望一行代码解决问题）<br>可读性很重要（优美的代码是可读的）<br>即便假借特例的实用性之名，也不可违背这些规则（这些规则至高无上）  </p><p>不要包容所有错误，除非你确定需要这样做（精准地捕获异常，不写 except:pass 风格的代码）  </p><p>当存在多种可能，不要尝试去猜测<br>而是尽量找一种，最好是唯一一种明显的解决方案（如果不确定，就用穷举法）<br>虽然这并不容易，因为你不是 Python 之父（这里的 Dutch 是指 Guido ）  </p><p>做也许好过不做，但不假思索就动手还不如不做（动手之前要细思量）  </p><p>如果你无法向人描述你的方案，那肯定不是一个好方案；反之亦然（方案测评标准）  </p><p>命名空间是一种绝妙的理念，我们应当多加利用（倡导与号召）  </p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-chan/">详情</a></p><h3 id="9-了解-dosctring-么？"><a href="#9-了解-dosctring-么？" class="headerlink" title="9.了解 dosctring 么？"></a>9.了解 dosctring 么？</h3><p>DocStrings 文档字符串是一个重要工具，用于解释文档程序，帮助你的程序文档更加简单易懂。</p><p>我们可以在函数体的第一行使用一对三个单引号 ‘’’ 或者一对三个双引号 “”” 来定义文档字符串。</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-docstring/">详情</a></p><p>你可以使用 <code>__doc__</code>（注意双下划线）  调用函数中的文档字符串属性</p><h3 id="10-了解类型注解么？"><a href="#10-了解类型注解么？" class="headerlink" title="10.了解类型注解么？"></a>10.了解类型注解么？</h3><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-type-annotation/">详情</a></p><h3 id="11-例举你知道-Python-对象的命名规范，例如方法或者类等"><a href="#11-例举你知道-Python-对象的命名规范，例如方法或者类等" class="headerlink" title="11.例举你知道 Python 对象的命名规范，例如方法或者类等"></a>11.例举你知道 Python 对象的命名规范，例如方法或者类等</h3><p>类：总是使用首字母大写单词串，如 MyClass(大驼峰命名)。</p><p>内部类可以使用额外的前导下划线。 变量：小写，由下划线连接各个单词。方法名类似常量：常量名所有字母大写 等</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-name-rule/">详情</a></p><h3 id="12-Python-中的注释有几种？"><a href="#12-Python-中的注释有几种？" class="headerlink" title="12.Python 中的注释有几种？"></a>12.Python 中的注释有几种？</h3><p>总体来说分为两种，单行注释和多行注释。</p><ul><li>单行注释在行首是 #。</li><li>多行注释可以使用三个单引号或三个双引号，包括要注释的内容。</li></ul><h3 id="13-如何优雅的给一个函数加注释？"><a href="#13-如何优雅的给一个函数加注释？" class="headerlink" title="13.如何优雅的给一个函数加注释？"></a>13.如何优雅的给一个函数加注释？</h3><h3 id="14-如何给变量加注释？"><a href="#14-如何给变量加注释？" class="headerlink" title="14.如何给变量加注释？"></a>14.如何给变量加注释？</h3><h3 id="15-Python-代码缩进中是否支持-Tab-键和空格混用。"><a href="#15-Python-代码缩进中是否支持-Tab-键和空格混用。" class="headerlink" title="15.Python 代码缩进中是否支持 Tab 键和空格混用。"></a>15.Python 代码缩进中是否支持 Tab 键和空格混用。</h3><p>不允许 tab 键和空格键混用，这种现象在使用 sublime 的时候尤为明显。</p><p>一般推荐使用 4 个空格替代 tab 键。</p><h3 id="16-是否可以在一句-import-中导入多个库"><a href="#16-是否可以在一句-import-中导入多个库" class="headerlink" title="16.是否可以在一句 import 中导入多个库?"></a>16.是否可以在一句 import 中导入多个库?</h3><p>可以是可以，但是不推荐。因为一次导入多个模块可读性不是很好，所以一行导入一个模块会比较好。</p><p>同样的尽量少用 from modulename import *，因为判断某个函数或者属性的来源有些困难，不方便调试，可读性也降低了。</p><h3 id="17-在给-Py-文件命名的时候需要注意什么"><a href="#17-在给-Py-文件命名的时候需要注意什么" class="headerlink" title="17.在给 Py 文件命名的时候需要注意什么?"></a>17.在给 Py 文件命名的时候需要注意什么?</h3><p>给文件命名的时候不要和标准库库的一些模块重复，比如 abc。 </p><p>另外要名字要有意义，不建议数字开头或者中文命名。</p><p>与标识符命名规则类似</p><h3 id="18-例举几个规范-Python-代码风格的工具"><a href="#18-例举几个规范-Python-代码风格的工具" class="headerlink" title="18.例举几个规范 Python 代码风格的工具"></a>18.例举几个规范 Python 代码风格的工具</h3><p>pylint 和 flake8</p><h3 style="color:inherit;line-height:inherit;font-weight:bold;border-bottom:2px solid rgb(239,112,96);font-size:1.3em;" id="-1"><span style="font-size:inherit;line-height:inherit;font-weight:normal;background:rgb(239,112,96);color:rgb(255,255,255);">数据类型</span><span style="vertical-align:bottom;border-bottom:36px solid rgb(239,235,233);border-right:20px solid transparent;"> </span></h3><h2 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h2><h3 id="19-列举-Python-中的基本数据类型？"><a href="#19-列举-Python-中的基本数据类型？" class="headerlink" title="19.列举 Python 中的基本数据类型？"></a>19.列举 Python 中的基本数据类型？</h3><p>就那6种么,<br>如需了解更多,你还可以去看<a href="https://blog.csdn.net/qq_40223983/article/details/95735483">详情</a></p><h3 id="20-如何区别可变数据类型和不可变数据类型"><a href="#20-如何区别可变数据类型和不可变数据类型" class="headerlink" title="20.如何区别可变数据类型和不可变数据类型"></a>20.如何区别可变数据类型和不可变数据类型</h3><p>说白了:就看内存地址和数据的值能不能对应上</p><h3 id="21-将”hello-world”转换为首字母大写”Hello-World”"><a href="#21-将”hello-world”转换为首字母大写”Hello-World”" class="headerlink" title="21.将”hello world”转换为首字母大写”Hello World”"></a>21.将”hello world”转换为首字母大写”Hello World”</h3><p>字符串操作函数:capitalize()</p><h3 id="22-如何检测字符串中只含有数字"><a href="#22-如何检测字符串中只含有数字" class="headerlink" title="22.如何检测字符串中只含有数字?"></a>22.如何检测字符串中只含有数字?</h3><p>isdigit()检测字符串是否由纯数字组成  十进制</p><p>isdecimal()纯数值字符串(中文的也好使)</p><h3 id="23-将字符串”ilovechina”进行反转"><a href="#23-将字符串”ilovechina”进行反转" class="headerlink" title="23.将字符串”ilovechina”进行反转"></a>23.将字符串”ilovechina”进行反转</h3><p>“ilovechina”[::-1]</p><h3 id="24-Python-中的字符串格式化方式你知道哪些？"><a href="#24-Python-中的字符串格式化方式你知道哪些？" class="headerlink" title="24.Python 中的字符串格式化方式你知道哪些？"></a>24.Python 中的字符串格式化方式你知道哪些？</h3><p>第一种：%</p><p>第二种:format()函数</p><h3 id="25-有一个字符串开头和末尾都有空格，比如“-adabdw-”-要求写一个函数把这个字符串的前后空格都去掉。"><a href="#25-有一个字符串开头和末尾都有空格，比如“-adabdw-”-要求写一个函数把这个字符串的前后空格都去掉。" class="headerlink" title="25.有一个字符串开头和末尾都有空格，比如“ adabdw ”,要求写一个函数把这个字符串的前后空格都去掉。"></a>25.有一个字符串开头和末尾都有空格，比如“ adabdw ”,要求写一个函数把这个字符串的前后空格都去掉。</h3><p>“ adabdw ”.strip()</p><h3 id="26-获取字符串”123456“最后的两个字符。"><a href="#26-获取字符串”123456“最后的两个字符。" class="headerlink" title="26.获取字符串”123456“最后的两个字符。"></a>26.获取字符串”123456“最后的两个字符。</h3><p>”123456“[-2::]</p><h3 id="27-一个编码为-GBK-的字符串-S，要将其转成-UTF-8-编码的字符串，应如何操作？"><a href="#27-一个编码为-GBK-的字符串-S，要将其转成-UTF-8-编码的字符串，应如何操作？" class="headerlink" title="27.一个编码为 GBK 的字符串 S，要将其转成 UTF-8 编码的字符串，应如何操作？"></a>27.一个编码为 GBK 的字符串 S，要将其转成 UTF-8 编码的字符串，应如何操作？</h3><p>a= “S”.encode(“gbk”).decode(“utf-8”,’ignore’)</p><h3 id="28-s-”info-xiaoZhang-33-shandong”-用正则切分字符串输出-‘info’-‘xiaoZhang’-‘33’-‘shandong’"><a href="#28-s-”info-xiaoZhang-33-shandong”-用正则切分字符串输出-‘info’-‘xiaoZhang’-‘33’-‘shandong’" class="headerlink" title="28.s=”info:xiaoZhang 33 shandong”,用正则切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]"></a>28.s=”info:xiaoZhang 33 shandong”,用正则切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line"> </span><br><span class="line">s = <span class="string">&quot;info：xiaoZhang 33 shandong&quot;</span></span><br><span class="line">res = re.split(<span class="string">r&quot;：| &quot;</span>, s)</span><br><span class="line">print(res)</span><br></pre></td></tr></table></figure><h3 id="27-怎样将字符串转换为小写？"><a href="#27-怎样将字符串转换为小写？" class="headerlink" title="27.怎样将字符串转换为小写？"></a>27.怎样将字符串转换为小写？</h3><p>使用字符串的 lower() 方法。</p><h3 id="28-单引号、双引号、三引号的区别？"><a href="#28-单引号、双引号、三引号的区别？" class="headerlink" title="28.单引号、双引号、三引号的区别？"></a>28.单引号、双引号、三引号的区别？</h3><p>单独使用单引号和双引号没什么区别，但是如果引号里面还需要使用引号的时候，就需要这两个配合使用了，</p><p>然后说三引号，同样的三引号也分为三单引号和三双引号，两个都可以声名长的字符串时候使用，如果使用 docstring 就需要使用三双引号。</p><h3 id="29-a-“你好-中国-“-去除多余空格只留一个空格。"><a href="#29-a-“你好-中国-“-去除多余空格只留一个空格。" class="headerlink" title="29.a = “你好     中国  “,去除多余空格只留一个空格。"></a>29.a = “你好     中国  “,去除多余空格只留一个空格。</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">s = <span class="string">&quot;你好     中国  &quot;</span></span><br><span class="line">print(<span class="string">&quot; &quot;</span>.join(s.split()))</span><br></pre></td></tr></table></figure><h2 id="列表"><a href="#列表" class="headerlink" title="列表"></a>列表</h2><h3 id="30-已知-AList-1-2-3-1-2-对-AList-列表元素去重，写出具体过程。"><a href="#30-已知-AList-1-2-3-1-2-对-AList-列表元素去重，写出具体过程。" class="headerlink" title="30.已知 AList = [1,2,3,1,2],对 AList 列表元素去重，写出具体过程。"></a>30.已知 AList = [1,2,3,1,2],对 AList 列表元素去重，写出具体过程。</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 用set去重</span></span><br><span class="line">AList = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="number">2</span>]</span><br><span class="line">result_list = <span class="built_in">list</span>(<span class="built_in">set</span>(AList))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 遍历判断</span></span><br><span class="line">AList = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="number">2</span>]</span><br><span class="line">result_list = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> AList:</span><br><span class="line"><span class="keyword">if</span> i <span class="keyword">not</span> <span class="keyword">in</span> result_list:</span><br><span class="line">result_list.append(i)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"><span class="keyword">continue</span></span><br><span class="line">print(result_list)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用pandas.unique()</span></span><br><span class="line">result_list = pandas.unique(AList).tolist()</span><br></pre></td></tr></table></figure><h3 id="31-如何实现-“1-2-3”-变成-“1”-”2”-”3”"><a href="#31-如何实现-“1-2-3”-变成-“1”-”2”-”3”" class="headerlink" title="31.如何实现 “1,2,3” 变成 [“1”,”2”,”3”]"></a>31.如何实现 “1,2,3” 变成 [“1”,”2”,”3”]</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">str</span>.split(<span class="string">&quot;,&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="32-给定两个-list，A-和-B，找出相同元素和不同元素"><a href="#32-给定两个-list，A-和-B，找出相同元素和不同元素" class="headerlink" title="32.给定两个 list，A 和 B，找出相同元素和不同元素"></a>32.给定两个 list，A 和 B，找出相同元素和不同元素</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">different_list = [i <span class="keyword">for</span> i <span class="keyword">in</span> A <span class="keyword">if</span> i <span class="keyword">not</span> <span class="keyword">in</span> B]</span><br></pre></td></tr></table></figure><h3 id="33-1-2-3-4-5-6-一行代码展开该列表，得出-1-2-3-4-5-6"><a href="#33-1-2-3-4-5-6-一行代码展开该列表，得出-1-2-3-4-5-6" class="headerlink" title="33.[[1,2],[3,4],[5,6]]一行代码展开该列表，得出[1,2,3,4,5,6]"></a>33.[[1,2],[3,4],[5,6]]一行代码展开该列表，得出[1,2,3,4,5,6]</h3><p>使用列表推导式</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[ j <span class="keyword">for</span> i <span class="keyword">in</span> question_list <span class="keyword">for</span> j <span class="keyword">in</span> i]</span><br></pre></td></tr></table></figure><h3 id="34-合并列表-1-5-7-9-和-2-2-6-8"><a href="#34-合并列表-1-5-7-9-和-2-2-6-8" class="headerlink" title="34.合并列表[1,5,7,9]和[2,2,6,8]"></a>34.合并列表[1,5,7,9]和[2,2,6,8]</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># solution 1</span></span><br><span class="line">A + B</span><br><span class="line"><span class="comment"># solution 2</span></span><br><span class="line">A.extend(B)</span><br></pre></td></tr></table></figure><h3 id="35-如何打乱一个列表的元素？"><a href="#35-如何打乱一个列表的元素？" class="headerlink" title="35.如何打乱一个列表的元素？"></a>35.如何打乱一个列表的元素？</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> random</span><br><span class="line">random.shuffle(demo_list)</span><br></pre></td></tr></table></figure><h2 id="字典"><a href="#字典" class="headerlink" title="字典"></a>字典</h2><h3 id="36-字典操作中-del-和-pop-有什么区别"><a href="#36-字典操作中-del-和-pop-有什么区别" class="headerlink" title="36.字典操作中 del 和 pop 有什么区别"></a>36.字典操作中 del 和 pop 有什么区别</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pop方法删除指定的键值对，并返回删除的值</span></span><br><span class="line">demo_dic = &#123;<span class="string">&quot;a&quot;</span>: <span class="number">1</span>, <span class="string">&quot;b&quot;</span>: <span class="number">2</span>, <span class="string">&quot;c&quot;</span>: <span class="number">3</span>&#125;</span><br><span class="line">pop_str = demo_dic.pop(<span class="string">&quot;a&quot;</span>)</span><br><span class="line">print(demo_dic)</span><br><span class="line">print(pop_str)</span><br><span class="line"><span class="comment"># &#123;&#x27;b&#x27;: 2, &#x27;c&#x27;: 3&#125;</span></span><br><span class="line"><span class="comment"># 返回值 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># del不会返回相应的值，只是将其删除</span></span><br><span class="line"><span class="keyword">del</span> demo_dic[<span class="string">&quot;b&quot;</span>]</span><br><span class="line">print(demo_dic)</span><br></pre></td></tr></table></figure><h3 id="37-按照字典的内的年龄排序"><a href="#37-按照字典的内的年龄排序" class="headerlink" title="37.按照字典的内的年龄排序"></a>37.按照字典的内的年龄排序</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">d1 = [  </span><br><span class="line">  &#123;<span class="string">&#x27;name&#x27;</span>: <span class="string">&#x27;alice&#x27;</span>, <span class="string">&#x27;age&#x27;</span>: <span class="number">38</span>&#125;,</span><br><span class="line">  &#123;<span class="string">&#x27;name&#x27;</span>: <span class="string">&#x27;bob&#x27;</span>, <span class="string">&#x27;age&#x27;</span>: <span class="number">18</span>&#125;,</span><br><span class="line">  &#123;<span class="string">&#x27;name&#x27;</span>: <span class="string">&#x27;ctrl&#x27;</span>, <span class="string">&#x27;age&#x27;</span>: <span class="number">28</span>&#125;</span><br><span class="line">]</span><br><span class="line">d1.sort(key=<span class="keyword">lambda</span> x: x[<span class="string">&#x27;age&#x27;</span>])</span><br></pre></td></tr></table></figure><h3 id="38-请合并下面两个字典-a-“A”-1-”B”-2-b-“C”-3-”D”-4"><a href="#38-请合并下面两个字典-a-“A”-1-”B”-2-b-“C”-3-”D”-4" class="headerlink" title="38.请合并下面两个字典 a = {“A”:1,”B”:2},b = {“C”:3,”D”:4}"></a>38.请合并下面两个字典 a = {“A”:1,”B”:2},b = {“C”:3,”D”:4}</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a.update(b)</span><br></pre></td></tr></table></figure><h3 id="39-如何使用生成式的方式生成一个字典，写一段功能代码。"><a href="#39-如何使用生成式的方式生成一个字典，写一段功能代码。" class="headerlink" title="39.如何使用生成式的方式生成一个字典，写一段功能代码。"></a>39.如何使用生成式的方式生成一个字典，写一段功能代码。</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成一个字典</span></span><br><span class="line">student_dict = &#123;name: <span class="string">&quot;student&quot;</span> <span class="keyword">for</span> name <span class="keyword">in</span> [<span class="string">&quot;Robin&quot;</span>, <span class="string">&quot;Bob&quot;</span>, <span class="string">&quot;James&quot;</span>]&#125;</span><br><span class="line"></span><br><span class="line">name_dic = &#123;<span class="number">1</span>: <span class="string">&quot;robin&quot;</span>, <span class="number">2</span>: <span class="string">&quot;bob&quot;</span>, <span class="number">3</span>: <span class="string">&quot;jams&quot;</span>&#125;</span><br><span class="line">result_dict = &#123;k: v.capitalize() <span class="keyword">for</span> k, v <span class="keyword">in</span> name_dict.items()&#125;</span><br></pre></td></tr></table></figure><h3 id="40-如何把元组-“a”-”b”-和元组-1-2-，变为字典-“a”-1-”b”-2"><a href="#40-如何把元组-“a”-”b”-和元组-1-2-，变为字典-“a”-1-”b”-2" class="headerlink" title="40.如何把元组(“a”,”b”)和元组(1,2)，变为字典{“a”:1,”b”:2}"></a>40.如何把元组(“a”,”b”)和元组(1,2)，变为字典{“a”:1,”b”:2}</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">tuple_key = (<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>)</span><br><span class="line">tuple_val = (<span class="number">1</span>, <span class="number">2</span>)</span><br><span class="line">result_dict = <span class="built_in">dict</span>(<span class="built_in">zip</span>(tuple_key, tuple_val))</span><br><span class="line">print(result_dict)</span><br></pre></td></tr></table></figure><h2 id="综合"><a href="#综合" class="headerlink" title="综合"></a>综合</h2><h3 id="41-Python-常用的数据结构的类型及其特性？"><a href="#41-Python-常用的数据结构的类型及其特性？" class="headerlink" title="41.Python 常用的数据结构的类型及其特性？"></a>41.Python 常用的数据结构的类型及其特性？</h3><p>字典中的键是不可变类型，可变类型list和dict不能作为字典键</p><p>一个对象能不能作为字典的key，就取决于其有没有__hash__方法</p><h3 id="42-如何将元组-“A”-”B”-和元组-1-2-合并成字典-“A”-1-”B”-2"><a href="#42-如何将元组-“A”-”B”-和元组-1-2-合并成字典-“A”-1-”B”-2" class="headerlink" title="42.如何将元组(“A”,”B”)和元组(1,2),合并成字典{“A”:1,”B”:2}"></a>42.如何将元组(“A”,”B”)和元组(1,2),合并成字典{“A”:1,”B”:2}</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">result_dict = &#123;v: k <span class="keyword">for</span> k, v <span class="keyword">in</span> demo_dict.items()&#125;</span><br></pre></td></tr></table></figure><h3 id="43-Python-里面如何实现-tuple-和-list-的转换？"><a href="#43-Python-里面如何实现-tuple-和-list-的转换？" class="headerlink" title="43.Python 里面如何实现 tuple 和 list 的转换？"></a>43.Python 里面如何实现 tuple 和 list 的转换？</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># tuple()</span></span><br><span class="line">result_tuple = <span class="built_in">tuple</span>(demo_list)</span><br><span class="line"></span><br><span class="line"><span class="comment"># list()</span></span><br><span class="line">result_list = <span class="built_in">list</span>(result_tuple)</span><br></pre></td></tr></table></figure><h3 id="44-我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？"><a href="#44-我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？" class="headerlink" title="44.我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？"></a>44.我们知道对于列表可以使用切片操作进行部分元素的选择，那么如何对生成器类型的对象实现相同的功能呢？</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 可以使用itertools.islice()对迭代器进行切片</span></span><br><span class="line"><span class="keyword">import</span> itertools</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fbnq</span>(<span class="params">num</span>):</span></span><br><span class="line">a, b = <span class="number">1</span>, <span class="number">1</span></span><br><span class="line"><span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(num):</span><br><span class="line">a, b = b, a+b</span><br><span class="line"><span class="keyword">yield</span> a</span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">gener = fbnq(<span class="number">20</span>)</span><br><span class="line">print(gener)</span><br><span class="line">gener_clip = itertools.islice(gener, <span class="number">10</span>, <span class="number">20</span>)</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> gener_clip:</span><br><span class="line">print(i)</span><br></pre></td></tr></table></figure><h3 id="45-请将-i-for-i-in-range-3-改成生成器"><a href="#45-请将-i-for-i-in-range-3-改成生成器" class="headerlink" title="45.请将[i for i in range(3)]改成生成器"></a>45.请将[i for i in range(3)]改成生成器</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(i <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">3</span>))    <span class="comment"># 方括号改为尖括号即可</span></span><br></pre></td></tr></table></figure><h3 id="46-a-”hello”和-b-”你好”编码成-bytes-类型"><a href="#46-a-”hello”和-b-”你好”编码成-bytes-类型" class="headerlink" title="46.a=”hello”和 b=”你好”编码成 bytes 类型"></a>46.a=”hello”和 b=”你好”编码成 bytes 类型</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a.encode()</span><br><span class="line">b.encode()</span><br></pre></td></tr></table></figure><h3 id="47-下面的代码输出结果是什么？"><a href="#47-下面的代码输出结果是什么？" class="headerlink" title="47.下面的代码输出结果是什么？"></a>47.下面的代码输出结果是什么？</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a = (<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,[<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>],<span class="number">8</span>)</span><br><span class="line">a[<span class="number">2</span>] = <span class="number">2</span></span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">a = (<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, [<span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>], <span class="number">8</span>)</span><br><span class="line">a[<span class="number">2</span>] = <span class="number">2</span>   </span><br><span class="line"></span><br><span class="line"><span class="comment"># TypeError: &#x27;tuple&#x27; object does not support item assignment</span></span><br></pre></td></tr></table></figure><h3 id="48-下面的代码输出的结果是什么"><a href="#48-下面的代码输出的结果是什么" class="headerlink" title="48.下面的代码输出的结果是什么?"></a>48.下面的代码输出的结果是什么?</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a = (<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,[<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>],<span class="number">8</span>)</span><br><span class="line">a[<span class="number">5</span>] = <span class="number">2</span></span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">a = (<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, [<span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>], <span class="number">8</span>)</span><br><span class="line">a[<span class="number">3</span>][<span class="number">0</span>] = <span class="number">2</span> </span><br><span class="line"><span class="comment"># (1, 2, 3, [2, 5, 6, 7], 8)</span></span><br></pre></td></tr></table></figure><p>元组中有可变数据类型，就可以修改可变数据类型中的值，修改可变数据类型的值并不会使其内存id发生变化。</p><h2 id="高级特性"><a href="#高级特性" class="headerlink" title="高级特性"></a>高级特性</h2><h3 id="70-函数装饰器有什么作用？请列举说明？"><a href="#70-函数装饰器有什么作用？请列举说明？" class="headerlink" title="70. 函数装饰器有什么作用？请列举说明？"></a>70. 函数装饰器有什么作用？请列举说明？</h3><p> 装饰器就是一个函数，它可以在不需要做任何代码变动的前提下给一个函数增加额外功能，启动装饰的效果。 它经常用于有切面需求的场景，比如：插入日志、性能测试、事务处理、缓存、权限校验等场景。 下面是一个日志功能的装饰器</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-decorator/">详情</a></p><h3 id="71-Python-垃圾回收机制？"><a href="#71-Python-垃圾回收机制？" class="headerlink" title="71. Python 垃圾回收机制？"></a>71. Python 垃圾回收机制？</h3><p>Python 不像 C++，Java 等语言一样，他们可以不用事先声明变量类型而直接对变量进行赋值。对 Python 语言来讲，对象的类型和内存都是在运行时确定的。这也是为什么我们称 Python 语言为动态类型的原因。</p><p>主要体现在下面三个方法：<br>-引用计数机制<br>-标记-清除<br>-分代回收</p><h3 id="72-魔法函数-call-怎么使用"><a href="#72-魔法函数-call-怎么使用" class="headerlink" title="72. 魔法函数 __call__怎么使用?"></a>72. 魔法函数 __call__怎么使用?</h3><p>将实例化的对象当做函数来调用</p><h3 id="73-如何判断一个对象是函数还是方法？"><a href="#73-如何判断一个对象是函数还是方法？" class="headerlink" title="73. 如何判断一个对象是函数还是方法？"></a>73. 如何判断一个对象是函数还是方法？</h3><h3 id="74-classmethod-和-staticmethod-用法和区别"><a href="#74-classmethod-和-staticmethod-用法和区别" class="headerlink" title="74. @classmethod 和@staticmethod 用法和区别"></a>74. @classmethod 和@staticmethod 用法和区别</h3><p>相同之处：@staticmethod 和@classmethod 都可以直接类名.方法名()来调用，不用在示例化一个类。<br>@classmethod 我们要写一个只在类中运行而不在实例中运行的方法。</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-class-decorator/">详情</a></p><h3 id="75-Python-中的接口如何实现？"><a href="#75-Python-中的接口如何实现？" class="headerlink" title="75. Python 中的接口如何实现？"></a>75. Python 中的接口如何实现？</h3><p>接口只是定义了一些方法，而没有去实现</p><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-interface/">详情</a></p><h3 id="76-Python-中的反射了解么"><a href="#76-Python-中的反射了解么" class="headerlink" title="76. Python 中的反射了解么?"></a>76. Python 中的反射了解么?</h3><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-reflect/">详情</a></p><h3 id="77-metaclass-作用？以及应用场景？"><a href="#77-metaclass-作用？以及应用场景？" class="headerlink" title="77. metaclass 作用？以及应用场景？"></a>77. metaclass 作用？以及应用场景？</h3><h3 id="78-hasattr-getattr-setattr-的用法"><a href="#78-hasattr-getattr-setattr-的用法" class="headerlink" title="78. hasattr() getattr() setattr()的用法"></a>78. hasattr() getattr() setattr()的用法</h3><h3 id="79-请列举你知道的-Python-的魔法方法及用途。"><a href="#79-请列举你知道的-Python-的魔法方法及用途。" class="headerlink" title="79. 请列举你知道的 Python 的魔法方法及用途。"></a>79. 请列举你知道的 Python 的魔法方法及用途。</h3><p>如需了解更多,你还可以去看<a href="https://victorfengming.gitee.io/blog/python-method/">详情</a></p><h3 id="80-如何知道一个-Python-对象的类型？"><a href="#80-如何知道一个-Python-对象的类型？" class="headerlink" title="80. 如何知道一个 Python 对象的类型？"></a>80. 如何知道一个 Python 对象的类型？</h3><h3 id="81-Python-的传参是传值还是传址？"><a href="#81-Python-的传参是传值还是传址？" class="headerlink" title="81. Python 的传参是传值还是传址？"></a>81. Python 的传参是传值还是传址？</h3><h3 id="82-Python-中的元类-metaclass-使用举例"><a href="#82-Python-中的元类-metaclass-使用举例" class="headerlink" title="82. Python 中的元类(metaclass)使用举例"></a>82. Python 中的元类(metaclass)使用举例</h3><h3 id="83-简述-any-和-all-方法"><a href="#83-简述-any-和-all-方法" class="headerlink" title="83. 简述 any()和 all()方法"></a>83. 简述 any()和 all()方法</h3><h3 id="84-filter-方法求出列表所有奇数并构造新列表，a-1-2-3-4-5-6-7-8-9-10"><a href="#84-filter-方法求出列表所有奇数并构造新列表，a-1-2-3-4-5-6-7-8-9-10" class="headerlink" title="84. filter 方法求出列表所有奇数并构造新列表，a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"></a>84. filter 方法求出列表所有奇数并构造新列表，a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]</h3><h3 id="85-什么是猴子补丁？"><a href="#85-什么是猴子补丁？" class="headerlink" title="85. 什么是猴子补丁？"></a>85. 什么是猴子补丁？</h3><h3 id="86-在-Python-中是如何管理内存的？"><a href="#86-在-Python-中是如何管理内存的？" class="headerlink" title="86. 在 Python 中是如何管理内存的？"></a>86. 在 Python 中是如何管理内存的？</h3><h3 id="87-当退出-Python-时是否释放所有内存分配？"><a href="#87-当退出-Python-时是否释放所有内存分配？" class="headerlink" title="87. 当退出 Python 时是否释放所有内存分配？"></a>87. 当退出 Python 时是否释放所有内存分配？</h3>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Flask 蓝图（Blueprint）使用方式解析</title>
      <link href="python/flask/flask-blueprint/"/>
      <url>python/flask/flask-blueprint/</url>
      
        <content type="html"><![CDATA[<p>本文转自:<a href="https://www.jianshu.com/p/95b584e4f76e">https://www.jianshu.com/p/95b584e4f76e</a></p><p>Flask蓝图提供了模块化管理程序路由的功能，使程序结构清晰、简单易懂。下面分析蓝图的使用方法</p><p>    假如说我们要为某所学校的每个人建立一份档案，一个很自然的优化方式就是这些档案如果能分类管理，就是说假如分为老师、学生、后勤人员等类别，那么后续查找和管理这些档案就方便清晰许多。Flask的蓝图就提供了类似“分类”的功能。</p><p>下面先上一张较大型程序的组织结构图</p><p><br></p><div class="image-package">    <div class="image-container" style="max-width: 274px; max-height: 305px; background-color: transparent;">        <div class="image-container-fill" style="padding-bottom: 111.31%;"></div>        <div class="image-view" data-width="274" data-height="305"><img                data-original-src="//upload-images.jianshu.io/upload_images/3986433-8846a26e0dfcee93.png"                data-original-width="274" data-original-height="305" data-original-format="image/png"                data-original-filesize="35561" class="" data-image-index="0" style="cursor: zoom-in;"                src="//upload-images.jianshu.io/upload_images/3986433-8846a26e0dfcee93.png?imageMogr2/auto-orient/strip|imageView2/2/w/274/format/webp">        </div>    </div>    <div class="image-caption">        <div>1</div>    </div></div><p>可以看到在app文件夹下有两个文件夹main和auth内含有视图函数，而main和auth就是注册的两个蓝图。</p><h4>1. 蓝图的创建及注册</h4><p>在图1中，以main文件夹为例。在main文件夹的__init__.py文件中，可创建蓝图，代码如下：</p><p><br></p><div class="image-package">    <div class="image-container" style="max-width: 303px; max-height: 130px; background-color: transparent;">        <div class="image-container-fill" style="padding-bottom: 42.9%;"></div>        <div class="image-view" data-width="303" data-height="130"><img                data-original-src="//upload-images.jianshu.io/upload_images/3986433-232c3555da7e247a.png"                data-original-width="303" data-original-height="130" data-original-format="image/png"                data-original-filesize="24573" class="" data-image-index="1" style="cursor: zoom-in;"                src="//upload-images.jianshu.io/upload_images/3986433-232c3555da7e247a.png?imageMogr2/auto-orient/strip|imageView2/2/w/303/format/webp">        </div>    </div>    <div class="image-caption">2</div></div><p>从Flask中导入Blueprint类，再创建一个实例即可。Blueprint接受两个参数实例化，分别为蓝本的名字和蓝本所在的包或模块，大多数情况下第二个参数使用Python 的__name__ 变量即可。</p><p><br></p><div class="image-package">    <div class="image-container" style="max-width: 514px; max-height: 111px; background-color: transparent;">        <div class="image-container-fill" style="padding-bottom: 21.6%;"></div>        <div class="image-view" data-width="514" data-height="111"><img                data-original-src="//upload-images.jianshu.io/upload_images/3986433-9b53b1e2c92d4f72.png"                data-original-width="514" data-original-height="111" data-original-format="image/png"                data-original-filesize="35580" class="" data-image-index="2" style="cursor: zoom-in;"                src="//upload-images.jianshu.io/upload_images/3986433-9b53b1e2c92d4f72.png?imageMogr2/auto-orient/strip|imageView2/2/w/514/format/webp">        </div>    </div>    <div class="image-caption">3</div></div><p>在图3中，是在Flask文件夹下的__init__.py文件中注册这两个模块（请结合图1理解文件夹的组织结构）。该__init__.py文件中包含app创建函数，创建app后，即可注册已创立的蓝图。</p><p>最后一部是在main文件夹下的view文件中导入创建的蓝图，使用from . import main命令。不要忘记这一步，应为视图函数实在view文件种定义的，不导入蓝图的话，无法用蓝图定义路由。</p><p>另请注意在图2中，在main = Blueprint('main', __name__) 命令下有一个from . import views,    errors命令。该命令的意思是导入在views和errors整个模块。在此我们发现views模块和__init__模块之间存在相互导入。一定要保证__init__模块中，from . import views,    error命令在main = Blueprint('main', __name__)之后，否则会产生依赖循环导入的错误。</p><h4>2.&nbsp;使用蓝图创建路由</h4><p>使用蓝图创建路由的示例如下图：</p><p><br></p><div class="image-package">    <div class="image-container" style="max-width: 363px; max-height: 88px; background-color: transparent;">        <div class="image-container-fill" style="padding-bottom: 24.240000000000002%;"></div>        <div class="image-view" data-width="363" data-height="88"><img                data-original-src="//upload-images.jianshu.io/upload_images/3986433-5eaea53732c9baa6.png"                data-original-width="363" data-original-height="88" data-original-format="image/png"                data-original-filesize="20124" class="" data-image-index="3" style="cursor: zoom-in;"                src="//upload-images.jianshu.io/upload_images/3986433-5eaea53732c9baa6.png?imageMogr2/auto-orient/strip|imageView2/2/w/363/format/webp">        </div>    </div>    <div class="image-caption">4</div></div><p>    该路由的创建有两点要注意，一是@main.route修饰器，在使用蓝图之前，所有的路由均通过@app.route注册，在此可对比创建蓝图后的不同。二是url_for函数的参数，该参数是一个“端点”名称，就是和在路由中定义的视图函数的名称，此处的‘    .index ’端点名是一种简写的方式，就是表示main蓝图下的index函数。如果我们要指向‘auth’蓝图下的index函数，应该使用‘ auth.index ’ 端点名称</p><p>    另请注意图4中生成的url和通过@app.route修饰器生成的url没有区别，是因为在注册main蓝图时（见图2）没有加“前缀”。回到图2，对比main蓝图和auth蓝图的注册，会发现auth在注册时多了一个url_prefix='/auth'    ，这个就是加的前缀。假如我们通过@auth.route('/student')创建了一个路由，那么我们在访问该路由时，要输入www.somehost.com/auth/student 才能行。</p><h4>3.    从蓝图回到全局</h4><p>创建蓝本后，会对Flask已定义的一些功能造成改变。例如在Flask中提供了一个before_request    钩子，通过该钩子，可以注册在请求之前必须先完成的函数。在创建蓝本前，当访问通过@app.route修饰器创建的所有路由时，均要先完成在钩子中注册的函数。但注册蓝本后，如果使用@main.before_request钩子，那么我们访问通过别的蓝本注册的路由时，可不用先完成在钩子中注册的函数。如果仍要保持“全局”的功能，应该使用@main.before_app_request钩子。</p><p>回到文章的起点，蓝本的使用是程序结构明晰，在后续使用中如果有其他心得，笔者会继续补充。<br></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> flask </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>兄弟会_flask笔记02</title>
      <link href="python/flask/flask-note2/"/>
      <url>python/flask/flask-note2/</url>
      
        <content type="html"><![CDATA[<h1 id="蓝图"><a href="#蓝图" class="headerlink" title="蓝图"></a>蓝图</h1><h3 id="什么是蓝图"><a href="#什么是蓝图" class="headerlink" title="什么是蓝图"></a>什么是蓝图</h3><p>用于实现单个应用的视图,模板,静态文件的集合<br>蓝图就是模块化处理的类</p><h3 id="为什么要用蓝图"><a href="#为什么要用蓝图" class="headerlink" title="为什么要用蓝图"></a>为什么要用蓝图</h3><p>随着业务代码的增加,把所有的代码都写进一个程序文件中是非常不合适的</p><p>这不仅</p><h3 id="readme-md"><a href="#readme-md" class="headerlink" title="readme.md"></a>readme.md</h3><p>微信小程序+flask 项目设计<br>图书借阅小程序<br>    图书列表<br>    图书详情<br>    图书查询<br>    图书录入<br>    图书借阅,归还<br>    个人中心,借阅信息</p><p>flask<br>    api 小程序api接口服务<br>    admin    后台管理<br>        图书管理<br>            添加<br>            查询<br>            修改<br>            下架<br>        借阅管理<br>            查看<br>            修改<br>        用户管理<br>            查看所有注册使用的用户,修改状态</p><p>查询到的数据json格式不能直接转换成为可用的类型</p><p>这可咋整        </p><p>我们需要处理一下才能转出去</p><h2 id="pymysql复习"><a href="#pymysql复习" class="headerlink" title="pymysql复习"></a>pymysql复习</h2><ol><li>连接mysql数据库</li><li>创建游标对象</li><li>执行sql语句</li><li>返回结果</li><li>关闭连接</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 导包</span></span><br><span class="line"><span class="keyword">import</span> pymysql</span><br><span class="line"> </span><br><span class="line"><span class="comment"># 打开数据库连接</span></span><br><span class="line">db = pymysql.connect(<span class="string">&quot;localhost&quot;</span>,<span class="string">&quot;testuser&quot;</span>,<span class="string">&quot;test123&quot;</span>,<span class="string">&quot;TESTDB&quot;</span> )</span><br><span class="line"> </span><br><span class="line"><span class="comment"># 使用 cursor() 方法创建一个游标对象 cursor</span></span><br><span class="line">cursor = db.cursor()</span><br><span class="line"> </span><br><span class="line"><span class="comment"># 使用 execute()  方法执行 SQL 查询 </span></span><br><span class="line">cursor.execute(<span class="string">&quot;SELECT VERSION()&quot;</span>)</span><br><span class="line"> </span><br><span class="line"><span class="comment"># 使用 fetchone() 方法获取单条数据.</span></span><br><span class="line">data = cursor.fetchone()</span><br><span class="line"> </span><br><span class="line"><span class="built_in">print</span> (<span class="string">&quot;Database version : %s &quot;</span> % data)</span><br><span class="line"> </span><br><span class="line"><span class="comment"># 关闭数据库连接</span></span><br><span class="line">db.close()</span><br></pre></td></tr></table></figure><h3 id="下面部分笔记没写"><a href="#下面部分笔记没写" class="headerlink" title="下面部分笔记没写"></a>下面部分笔记没写</h3><ul><li>课时5：模型的返回问题分析15 分45 秒</li><li>课时6：封装pymysql36 分43 秒</li><li>课时7：书籍表设计20 分22 秒</li><li>课时8：书籍表单设计26 分39 秒</li><li>课时9：图书信息的添加30 分8 秒</li><li>课时10：图书管理的列表显示</li></ul><p>详情参考:<a href="https://github.com/victorfengming/xdh_flask_project">https://github.com/victorfengming/xdh_flask_project</a></p><p>初级程序员是为了实现功能,而中高级程序员是在优化性能</p><p>花生壳</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> flask </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>简述编译型与解释型编程语言</title>
      <link href="cp/compile-explain/"/>
      <url>cp/compile-explain/</url>
      
        <content type="html"><![CDATA[<article class="article-content">    <h2>概念：</h2><ul type="disc">    <li>编译型语言：把做好的源程序全部编译成二进制代码的可运行程序。然后，可直接运行这个程序。</li>    <li>解释型语言：把做好的源程序翻译一句，然后执行一句，直至结束！</li></ul><h2>区别：</h2><ul type="disc">    <li>编译型语言，执行速度快、效率高；依赖编译器、跨平台性差些。如C、C++、Delphi、Pascal，Fortran。</li>    <li>解释型语言，执行速度慢、效率低；依赖解释器、跨平台性好。如Java、Basic.</li></ul><p><strong>通俗的讲，编译语言是在编译后可以直接运行，而解释语言的执行需要一个解释环境。</strong></p><p><strong>&nbsp;java很特殊，java程序也需要编译，但是没有直接编译称为机器语言，而是编译称为字节码，然后用解释方式执行字节码。</strong></p><p>**********************************************************************************************</p><p>计算机不能直接理解高级语言，只能直接理解机器语言，所以必须要把高级语言翻译成机器语言，计算机才能值型高级语言编写的程序。</p><p>翻译的方式有两种，一个是编译，一个是解释。两种方式只是翻译的<strong>时间不同</strong>。编译型语言写的程序执行之前，需要一个专门的编译过程，把程序编译成为机器语言的文件，比如exe文件，以后要运行的话就不用重新翻译了，直接使用编译的结果就行了（exe文件），因为翻译只做了一次，运行时不需要翻译，所以编译型语言的程序执行效率高。</p><p>    解释则不同，解释性语言的程序不需要编译，省了道工序，解释性语言在运行程序的时候才翻译，比如解释性basic语言，专门有一个解释器能够直接执行basic程序，每个语句都是执行的时候才翻译。这样解释性语言每执行一次就要翻译一次，效率比较低。</p><p>编译型与解释型，两者各有利弊。前者由于程序执行速度快，同等条件下对系统要求较低，因此像开发操作系统、大型应用程序、数据库系统等时都采用它，像C/C++、Pascal/Object    Pascal（Delphi）等都是编译语言，而一些网页脚本、服务器脚本及辅助开发接口这样的对速度要求不高、对不同系统平台间的兼容性有一定要求的程序则通常使用解释性语言，如JavaScript、VBScript、Perl、Python、Ruby、MATLAB    等等。</p><p>java很特殊，java程序也需要编译，但是没有直接编译称为机器语言，而是编译称为字节码，然后用解释方式执行字节码。</p><p>但随着硬件的升级和设计思想的变革，编译型和解释型语言越来越笼统，主要体现在一些新兴的高级语言上，而解释型语言的自身特点也使得编译器厂商愿意花费更多成本来优化解释器，解释型语言性能超过编译型语言也是必然的。</p><p>    在具体计算机上实现一种语言，首先要确定的是表示该语言语义解释的虚拟计算机，一个关键的问题是程序执行时的基本表示是实际计算机上的机器语言还是虚拟机的机器语言。这个问题决定了语言的实现。根据这个问题的回答，可以将程序设计语言划分为两大类：编译型语言和解释型语言。</p><p><strong>编译型语言：</strong><br>    编译是指在应用源程序执行之前，就将程序源代码“翻译”成目标代码(机器语言)，因此其目标程序可以脱离其语言环境独立执行，使用比较方便、效率 较高。但应用程序一旦需要修改，必须先修改源代码，再重新编译生成新的目标文件(＊    .OBJ)才能执行，只有目标文件而没有源代码，修改很不方便。现在大多数的编程语言都是编译型的。编译程序将源程序翻译成目标程序后保存在另一个文件中，该目标程序可脱离编译程序直接在计算机上多次运行。大多数软件产品都是以目标程序形式发行给用户的，不仅便于直接运行，同时又使他人难于盗用其中的技术C、C++、Fortran、Visual    Foxpro、Pascal、Delphi、Ada都是编译实现的。</p><p><strong>解释型语言：</strong><br>    解释型语言的实现中，翻译器并不产生目标机器代码，而是产生易于执行的中间代码，这种中间代码与机器代码是不同的，中间代码的解释是由软件支持的，不能直接使用硬件，软件解释器通常会导致执行效率较低。用解释型语言编写的程序是由另一个可以理解中间代码的解释程序执行的。与编译程序不同的是，解释程序的任务是逐一将源程序的语句解释成可执行的机器指令，不需要将源程序翻译成目标代码后再执行。释程序的优点是当语句出现语法错误时，可以立即引起程序员注意，而程序员在程序开发期间就能进行校正。对于解释型Basic语言，需要一个专门的解释器解释执行    Basic程序，每条语言只有在执行才被翻译。这种解释型语言每执行一次就翻译一次，因而效率低下。一般地，动态语言都是解释型的，如Tcl、Perl、Ruby、VBScript、 JavaScript等。</p><p><strong>混合型：</strong><br>    Java很特殊，Java程序也需要编译，但是没有直接编译称为机器语言，而是编译称为字节码，然后在Java虚拟机上用解释方式执行字节码。Python    的也采用了类似Java的编译模式，先将Python程序编译成Python字节码，然后由一个专门的Python字节码解释器负责解释执行字节码。(Java虚拟机对字节码的执行相当于模拟一个cpu，而ruby1.8–在虚拟机还未出现前–是通过解释成语法树执行。)</p><p>**********************************************************************************************</p><h1>解释型的编程语言</h1><p>    我们知道，任何编程语言编写的程序归根到底都是由底层机器的机器代码（01序列）执行的，无论是编译型语言还是解释型语言。而任何高级编程语言程序的源代码都是一个字符序列，这个字符序列到底层的01序列是通过编译器或解析器经过多次转换完成的。</p><p><img src= "/img/loading.gif" data-lazy-src="http://www.i3geek.com/wp-content/uploads/2014/11/031837OON.gif" alt="" data-tag="bdshare"></p><p>图1 编程语言的层次结构</p><p>    这个层次结构中，从高到低越来越接近于机器硬件。机器代码就是01序列，汇编语言就是描述本地机器的指令集体系结构，而高级语言就包含相应的数据结构和语法结构，更接近人类的语言习惯。因此，层次越高就越面向于人类。在计算机科学中，CPU被抽象为指令集体系结构，这个指令集描述了CPU所有完成的所有功能。所有的程序都经过编译或解释转化为这个指令集表示的机器程序。在指令集中指令可以按功能划分为：</p><p>1. 数据传输指令，用于读写内存、寄存器。</p><p>2. 算术与逻辑运算指令，比如：addl执行双字（32bit）的加法，andl双字的按位与。</p><p>3. 控制流指令，用于实现高级编程语言中的分支、循环等控制结构。</p><p>4. 过程调用指令，用于实现函数调用，分配、恢复栈帧等操作。</p><p>通过观察C程序的机器代码可以发现由C程序转化为机器代码，主要有数据类型和控制结构的转换。下面以x86指令集说明：</p><p>1. 数据类型的转换：在底层，x86指令对于数据是不区分逻辑类型的，也就是不分int，float，double。所有的数据按照其所占的字节数被归类为字（16个字节，Word）、双字（32个字节，Double    Words）、四字（64个字节，Quad    Words）。一个指令操作的数据类型是由这个指令的后缀表示的，比如mov指令，movw操作字，movl操作双字。也就是说高级语言的程序中的不同数据类型反映到底层指令集上主要体现是指令的不同。比如，将上述C程序中的result类型改为short，在相应的汇编代码中的mov指令会由movl转换为movw。当然，还有一个问题就是C语言中的具体数据类型，在机器代码中是如何存储表示的。这应该是gcc编译器的职责，比如对于int，首先gcc需要知道底层指令集如何编码int，采用什么编码方式，字节顺序是Big-endian还是Little-endian等。在知道底层的实现方式后gcc才能将表示整型数字的字符串编码为相应的二进制形式。而对于数组、struct和union这些数据结构会转化为相应的内存地址加偏移量的形式。</p><p>2.    控制结构的转换：控制结构就是执行指令的流程。在x86中，所有的指令集都是顺序执行。要实现分支、循环等结构，必须具备go形式的跳转指令，以及相应的条件判断指令。CPU中有一组条件码寄存器，指示算术或逻辑运算的状态（计算结果是否溢出、为0或者是负数等）。执行条件运算指令可以测试一个条件，比如”cmpl    $1, %edx”比较直接数1与寄存器%edx中存放的数的大小，并将结果存入条件码寄存器中。接下来执行条件跳转指令，根据条件码寄存器中的状态进行判断是否进行跳转。比如“jg    .L10”是在前一条的cmpl指令结果返回大于的情况跳转到L10，否则执行下一条指令。</p><p>    当然，在进行函数调用时，还要在底层用机器码对其进行描述。我们知道，计算机科学中用栈来实现函数的调用（叫做调用栈），栈中存放栈帧。每一次函数调用对应一个栈帧，栈帧中包含该方法的局部变量、保存的寄存器值等数据。这样函数的调用和返回就对应着栈帧的入栈和出栈。CPU的寄存器组中，有两个专门用于实现方法调用，分别是%esp和%ebp。%esp是栈指针寄存器，存放当前函数栈栈顶的内存地址。%ebp是帧指针寄存器，在%esp和%ebp之间的内存地址序列就对应于当前函数的栈帧。由于函数调用、返回与栈帧的关系很密切，所以可以将以此函数调用过程描述为：</p><p>1. 初始化被调用函数的栈帧，并将其入栈。也就是调用函数过程，通过call指令实现。</p><p>2. 执行被调用函数。</p><p>3. 恢复调用函数的栈帧，将被调用函数的栈帧出栈。也就是函数返回的过程，通过ret指令实现。</p><p>对于初始化、恢复栈帧实际上都是%esp和%ebp的调整，还要包括传参和返回值的问题，这些都是由编译器实现的。</p><p>    上面介绍了C语言和机器语言的关系，下面看一下其他类型语言的实现机制。首先，我们可以把编程语言分为编译型语言、解释型语言和虚拟机语言。编译型语言直接被编译成本地机器代码，比如C、C++。解释型语言是通过解释器执行，比如javascript、shell、python等。虚拟机语言运行在虚拟机上，需要被编译成虚拟机代码，由虚拟机执行，比如java。虽然python也有自己的虚拟机，但是不需要编译，所以把它归类为解释型语言。</p><p><img src= "/img/loading.gif" data-lazy-src="http://www.i3geek.com/wp-content/uploads/2014/11/031838AKN.gif" alt="" data-tag="bdshare"></p><p>图2 编程语言实现结构</p><p>    通过上文的分析、我们知道对于一门语言最重要的是数据类型、控制结构和语法结构以及系统调用。从上图可以看出，C和C++更接近于底层硬件，但是不能像汇编语言一样可以直接访问寄存器等硬件。而python和java相对于C和C++的抽象层次又高了一层，它们不能通过指针直接访问内存。从机器语言-&gt;汇编语言-&gt;系统语言（C和C++）-&gt;解释型语言（python）和虚拟机语言（java），抽象层次越来越高，越贴近于人的思维，不需要考虑那么多细节；同时，程序员的自由度和程序的运行速度越来越低。下面从低向高j讨论一下。</p><p>    在底层，汇编语言会经过汇编器转换为机器代码。比如，通过gcc编译C程序时，会调用汇编器进行汇编。通过汇编器和汇编语言这一层次，可以很好的隔离底层机器硬件的实现细节。不同的处理器具有与之对应的汇编器，将汇编语言汇编成该处理器支持的指令集。这样就是实现了汇编语言这一层的移植性。</p><p>在C和C++系统编程语言这一层，会通过编译器完成语言元素到汇编语言的映射。比如前文描述的，数据类型、控制结构、函数调用等结构的转换。</p><p>    python是解释型语言，它通过python解释器实现向底层语言的映射。我们知道python虚拟机是由C语言编写的，所以python程序会转化为C程序而执行。比如，python中的所有对象都会在C中有对应的PyObject结构体。python的list、dict等数据类型也要在C中有对应的表示。而像生成器、迭代器等语法结构需要相应的支持。</p><p>    而虚拟机是模拟一个指令集的程序，所以它自身有一套独立于具体硬件、操作系统的指令集。需要通过底层语言实现这套指令集。虚拟机本身也有自己的数据类型系统、语言结构等。比如，java虚拟机上支持的数据类型有基本数据类型和引用类型，也支持tableswitch和lookupswitch等实现switch语法结构的字节码指令。对于这些语言元素映射到底层语言的实现方式可以不同的方式。首先是解释器模式转化为C++，还有就是JIT直接编译成本地机器代码。</p><p>像java这样的虚拟机语言会被编译器编译成虚拟机本地的机器代码，然后再虚拟机上执行，这里就需要向javac编译器实现java语言的数据类型、语言结构和java虚拟机上的数据类型、语法结构的映射。</p><p>    通过谈论，可以看出编译器和解释器以及虚拟机在编程语言中的重要性，它们都是编程语言可以在计算机上运行的基石。一门编程语言的编译器、解释器或者虚拟机可以很大程度上影响这门语言的执行效率。因为它们在进行语言转换时会进行很多的优化以提高执行效率。这也是为什么JVM上有那么多优秀的语言，因为JVM很强大。所以，要深入语言的底层，要学会编译器、解释器和虚拟机的实现，这方面还需要下功夫啊。</p><p>**********************************************************************************************</p><p><strong>1.动态语言Dynamically&nbsp;Typed&nbsp;Language</strong></p><p>例如：ECMAScript(JavaScript)、Ruby、Python、VBScript、php</p><p>也叫动态类型定义语言</p><p>与静态类型定义相反，一种在执行期间才去发现数据类型的语言，</p><p>动态语言是指程序在运行时可以改变其结构：新的函数可以被引进，已有的函数可以被删除等在结构上的变化。</p><p>动态语言的类型检查是在运行时做的。</p><p>它的优点是方便阅读，不需要写非常多的类型相关的代码；</p><p>缺点是不方便调试，命名不规范时会造成读不懂，不利于理解等。</p><p>目前java平台下的动态语言有Groovy、nice、BeanShell、Jython、JRuby、Rhino(JavaScript)、    Jacl(TCL)、Bistro(SmallTalk)、Kawa(Lisp/Schema)，真是越来越多了。java下这么多的动态语言建议选择    Groovy，感觉血统较为正宗，兼容Java的语法，java程序员学习起来较为容易，上手较快。</p><p><strong>2.静态语言Statically&nbsp;Typed&nbsp;Language</strong></p><p>例如：C、C++、Java</p><p>也叫静态类型定义语言。即一种在编译时，数据类型是固定的语言。大多数静态类型定义语言强制这一点，它要求你在使用所有变量之前要声明它们的数据类型。</p><p>在使用数据之前，我们必须首先定义数据类型，这些数据类型包括int ,float,double等等。就相当于在使用它们之前，首先要为它们分配好内存空间。</p><p>静态类型语言的主要优点在于其结构非常规范，便于调试，方便类型安全；</p><p>缺点是为此需要写更多的类型相关代码，导致不便于阅读、不清晰明了。</p><p><strong>3.强类型定义语言</strong></p><p>一种总是强制类型定义的语言。Java和Python是强制类型定义的。如果你有一个整数，如果不显示地进行转换，你不能将其视为一个字符串</p><p><strong>4.弱类型定义语言</strong></p><p>一种类型可以被忽略的语言，与强类型定义相反。VBScript是弱类型定义</p><p>的。在VBScript中，可以将字符串 ’12′ 和整数 3 进行连接得到字符串 ’123′，</p><p>然后可以把它看成整数 123，而不需要显示转换。</p><p><strong>5.脚本语言</strong></p><p>脚本语言代表一套与系统程序设计语言不同的协定。</p><p>它们牺牲执行速度和与系统程序设计语言相关的类型长度而提供更高的编程创作力和软件重用。</p><p>脚本语言更适合在联系复杂的应用程序中进行胶着。</p><p>为了简化连接组件的工作,脚本语言被设计为无类型的，脚本语言一般是面向字符的，因为字符为许多不同的事物提供了一致的描述。</p><p>事实上，脚本语言都是动态语言，而动态语言都是解释型语言，不管它们是不是面向对象。</p></article>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>如何理解面向过程、面向对象、面向切面？它们有什么区别</title>
      <link href="cp/oop-opp-aop/"/>
      <url>cp/oop-opp-aop/</url>
      
        <content type="html"><![CDATA[<article class="_2rhmJa"><p>我们总会听见如下词语：</p>    <h1>起步</h1>    <p>面向过程编程（opp）<br>        面向对象编程（oop）<br>        面向切面编程（aop）</p>    <p>上面几个词语，都是编程范式。</p>    <p>编程范式是指：编程时所秉承的思想和风格，不同的编程语言对各大编程范式会有不同程度的支持。</p>    <p>不同的编程范式各自会有自己的优点，它们适用在各种不同的情况下：面向过程性能很高，面向对象比较易于管理和维护，面向切面使软件变得更灵活。</p>    <p>在理解编程范式之前，我们一定要知道：</p>    <p><strong>新的编程范式，并不一定完全各方面都优于旧的编程范式，它们只是在某一特定领域或特殊场景下有着独到的优势。</strong></p>    <blockquote>        <p>编程范式只有适合不适合项目特性，没有绝对的好坏。</p>    </blockquote>    <h1>OPP和OOP</h1>    <p>OPP是较贴近计算机执行的编程范式。</p>    <p>它主要关注“怎么做”，即完成任务的具体细节。</p>    <p>OOP则是比较贴近人类思维的一种编程范式，它主要关注的是“谁来做”，也就是完成任务的对象，而非细节。</p>    <p>面向过程会将一个任务拆分成各个小的步骤，然后用一个个函数来实现每一个小步骤，再在主函数中依次调用这些函数，以此来完成任务。</p>    <p>面向对象则是从一个任务中抽取出各个角色（对象），这些角色分别提供了一些能力，然后，这些拥有能力的对象互相配合，完成任务，这样的好处是：<strong>各个对象可以通过不同的组合，完成不同的任务，这样可以提升代码重用，对代码做好分类和分级</strong>    </p>    <h2>举例对比</h2>    <p>比如完成吃饭这个任务。</p>    <p>面向过程的写法，需要封装一个eat()函数：</p>    <ul>        <li>如果是狗吃饭，则eat(狗,饭)</li>        <li>如果是人吃肉，则eat(人,肉)</li>    </ul>    <p>如上，eat是人和狗共用的吃饭能力。</p>    <p>那么，如果狗吃饭要嚼10下，人吃肉要嚼20下。</p>    <p>这时候，我们就需要在eat函数中，判断传入的第一个参数是人还是狗，然后再执行嚼的次数。</p>    <p>那如果之后要处理猫吃鱼、老虎吃人、猫走路、老虎走路…</p>    <p>eat函数中就会存在大量的if…else的判断，这段代码，无疑是很恶心的，另外，因为存在走路的功能，还需要定义一个恶心的walk函数，这不易于维护、升级、扩展。</p>    <p>但如果是面向对象，如何来解决这个问题呢？</p>    <p>这里涉及到“抽象”这个思维。</p>    <p>我们可以发现，狗、猫、人、老虎，它们都有吃的能力，所以，我们需要抽象出它们的祖先：<strong>会吃东西的动物</strong>。</p>    <p>然后，再抽象出狗、猫、人、老虎，继承会出东西的动物，以此来决定它们都具备吃东西的能力。</p>    <p>接着，解决上面的问题。</p>    <p>狗、猫、人、老虎各自有自己的eat方法，也各自有自己的walk方法。</p>    <p>当我们想要进行狗吃肉，那就“狗-&gt;eat(肉)”，这样，我们从面向过程维护eat的焦点，转移到了面向对象维护角色的焦点上来。我们只需要维护好不同的角色（类）就好了，并且狗的eat不会影响到猫的eat，猫的eat也不会影响到人的eat。</p>    <p>所以，oop思想非常贴近软件工程高内聚的思想：<strong>自己管好自己的东西，自己做好自己的事情。</strong></p>    <p>上面，主要是从思想上讲述了opp和oop之间的差异，如果深入oop，不同的语言也会提供不同程度的支持，比如继承、多态、封装这些，比较深入的内容，不是本文讨论的主题。</p>    <blockquote>        <p>            大多数支持面向对象的语言，同时也支持面向过程，不论是java、php，还是javascript，它们都还无法完全面向对象，因为面向过程是必然的，面向过程代表着必要的程序流程，调动对象进行组合或对象内部能力的实现，都一定会存在“过程”，它最终还是需要通过拆分步骤来指导最具体的执行细节。</p>    </blockquote>    <p>        在此，我们也能得到一些感悟，许多事情并非完全非黑即白，非oop就必然是opp，特别是思想层面的东西，它们呈现出互相结合的形态，从opp到oop，这是一个思想进步的过程，也是人们遇到“管理问题”、“可持续发展问题”后对“管理”和“发展”提出的讨论和求证。</p>    <h1>AOP</h1>    <p>面向切面编程，AOP也是一种编程范式，是对oop的延续。</p>    <p>即：<strong>基于oop延伸出来的编程思想，它进一步降低项目合作、维护、扩展、多人协作的成本，提高程序的内聚性，降低程序的耦合度。</strong></p>    <p>那么，AOP如何体现？</p>    <p>这里，可以联想一下laravel的中间件、javaweb的拦截器、vue的Decorator…它们都是AOP思想的实践。</p>    <p>也可以联想一下，装饰器模式、代理模式，它们也是基于AOP思想的设计模式。</p>    <p>这里以laravel的中间件（middleware）作为详细例子：</p>    <p>middleware所运行的地方，就是一个切面，这个切面上承路由，下接controller。</p>    <blockquote>        <p>想象一下，laravel从接收到请求一路运行下来，到中间件这里，就好像是被切开了一个平整面，这就是面向切面。</p>    </blockquote>    <p><strong>而AOP思想，指导我们通过找到平整切面的形式，插入新的代码，使新插入的代码对切面上下原有流程的伤害降到最低。</strong></p>    <p>举更具体的例子：</p>    <p>我们拿laravel中间件做什么？</p>    <p>权限、日志、请求过滤、请求频率限制、csrf过滤……</p>    <p>我们知道，中间件对于controller的业务逻辑，不会有任何伤害。</p>    <p>如果没有这个切面，我们想要记录请求日志，可能需要在每个controller的具体方法中写日志记录的代码，或者调用日志记录的函数、方法。</p>    <p>这会使一段记录日志的代码，或调用记录日志的调用语句出现在许多controller中，这与controller原本要关注的逻辑无关，使controller职责不单一，提高维护成本。</p>    <p>当然，我们可能会写一个父类，让许多controller来继承这个父类，然后统一在父类的__construct方法中记录日志，以此来解决耦合问题。</p>    <p>但实际上，这不父类的construct方法，不正是一个切面吗？它在原有流程中截取了一个切面，在切面中植入代码，以达到承上启下的作用，并且不对上下文产生伤害。</p>    <blockquote>        <p>            从这个例子中，我们也能得出另外一个思考：AOP指导我们寻找切面，但找到合适的切面，也尤为重要。就像上文，父类构造函数的切面和中间件的切面比起来，显然中间件这个切面更利于维护，你可以灵活选择中间件，但你无法灵活选择父类，因为决定你的controller继承什么父类的，不是切面中的代码，而是controller本身处理什么逻辑。</p>    </blockquote>    <p>另外，TP常会提到的钩子和行为，也是AOP思想的一种实践。</p>    <p>aop的思想，是对oop的补充。</p>    <p>而oop又是对opp的升级。</p>    <blockquote>        <p><strong>许多项目，opp、oop、aop是同时存在的，它们是编程范式，是一种指导编程的思想，并非不能互相配合。</strong></p>    </blockquote></article>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> oop </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python之禅</title>
      <link href="cp/python/python-chan/"/>
      <url>cp/python/python-chan/</url>
      
        <content type="html"><![CDATA[<p>可以在编译器里面输入如下语句来查看python语言的设计哲学：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">C:\Users\victor&gt;python</span><br><span class="line">Python <span class="number">3.7</span><span class="number">.2</span> (tags/v3<span class="number">.7</span><span class="number">.2</span>:9a3ffc0492, Dec <span class="number">23</span> <span class="number">2018</span>, <span class="number">23</span>:09:<span class="number">28</span>) [MSC v<span class="number">.1916</span> <span class="number">64</span> bit (AMD64)] on win32</span><br><span class="line">Type <span class="string">&quot;help&quot;</span>, <span class="string">&quot;copyright&quot;</span>, <span class="string">&quot;credits&quot;</span> <span class="keyword">or</span> <span class="string">&quot;license&quot;</span> <span class="keyword">for</span> more information.</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">import</span> this</span><br><span class="line">The Zen of Python, by Tim Peters</span><br><span class="line"></span><br><span class="line">Beautiful <span class="keyword">is</span> better than ugly.</span><br><span class="line">Explicit <span class="keyword">is</span> better than implicit.</span><br><span class="line">Simple <span class="keyword">is</span> better than <span class="built_in">complex</span>.</span><br><span class="line">Complex <span class="keyword">is</span> better than complicated.</span><br><span class="line">Flat <span class="keyword">is</span> better than nested.</span><br><span class="line">Sparse <span class="keyword">is</span> better than dense.</span><br><span class="line">Readability counts.</span><br><span class="line">Special cases aren<span class="string">&#x27;t special enough to break the rules.</span></span><br><span class="line"><span class="string">Although practicality beats purity.</span></span><br><span class="line"><span class="string">Errors should never pass silently.</span></span><br><span class="line"><span class="string">Unless explicitly silenced.</span></span><br><span class="line"><span class="string">In the face of ambiguity, refuse the temptation to guess.</span></span><br><span class="line"><span class="string">There should be one-- and preferably only one --obvious way to do it.</span></span><br><span class="line"><span class="string">Although that way may not be obvious at first unless you&#x27;</span>re Dutch.</span><br><span class="line">Now <span class="keyword">is</span> better than never.</span><br><span class="line">Although never <span class="keyword">is</span> often better than *right* now.</span><br><span class="line">If the implementation <span class="keyword">is</span> hard to explain, it<span class="string">&#x27;s a bad idea.</span></span><br><span class="line"><span class="string">If the implementation is easy to explain, it may be a good idea.</span></span><br><span class="line"><span class="string">Namespaces are one honking great idea -- let&#x27;</span>s do more of those!</span><br></pre></td></tr></table></figure><p>中英文释义如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">Beautiful <span class="keyword">is</span> better than ugly.</span><br><span class="line"><span class="comment"># 优美胜于丑陋（Python以编写优美的代码为目标）</span></span><br><span class="line">Explicit <span class="keyword">is</span> better than implicit.</span><br><span class="line"><span class="comment"># 明了胜于晦涩（优美的代码应当是明了的，命名规范，风格相似） </span></span><br><span class="line">Simple <span class="keyword">is</span> better than <span class="built_in">complex</span>.</span><br><span class="line"><span class="comment"># 简洁胜于复杂（优美的代码应当是简洁的，不要有复杂的内部实现） </span></span><br><span class="line">Complex <span class="keyword">is</span> better than complicated.</span><br><span class="line"><span class="comment"># 复杂胜于凌乱（如果复杂不可避免，那代码间也不能有难懂的关系，要保持接口简洁）</span></span><br><span class="line">Flat <span class="keyword">is</span> better than nested.</span><br><span class="line"><span class="comment"># 扁平胜于嵌套（优美的代码应当是扁平的，不能有太多的嵌套） </span></span><br><span class="line">Sparse <span class="keyword">is</span> better than dense.</span><br><span class="line"><span class="comment"># 间隔胜于紧凑（优美的代码有适当的间隔，不要奢望一行代码解决问题） </span></span><br><span class="line">Readability counts.</span><br><span class="line"><span class="comment"># 可读性很重要（优美的代码是可读的） </span></span><br><span class="line">Special cases aren<span class="string">&#x27;t special enough to break the rules.</span></span><br><span class="line"><span class="string">Although practicality beats purity.</span></span><br><span class="line"><span class="string"># 即便假借特例的实用性之名，也不可违背这些规则（这些规则至高无上） </span></span><br><span class="line"><span class="string">Errors should never pass silently.</span></span><br><span class="line"><span class="string">Unless explicitly silenced.</span></span><br><span class="line"><span class="string"># 不要包容所有错误，除非你确定需要这样做（精准地捕获异常，不写except:pass风格的代码） </span></span><br><span class="line"><span class="string">In the face of ambiguity, refuse the temptation to guess.</span></span><br><span class="line"><span class="string"># 当存在多种可能，不要尝试去猜测 </span></span><br><span class="line"><span class="string">There should be one-- and preferably only one --obvious way to do it.</span></span><br><span class="line"><span class="string"># 而是尽量找一种，最好是唯一一种明显的解决方案（如果不确定，就用穷举法） </span></span><br><span class="line"><span class="string">Although that way may not be obvious at first unless you&#x27;</span>re Dutch.</span><br><span class="line"><span class="comment"># 虽然这并不容易，因为你不是 Python 之父（这里的Dutch是指Guido）</span></span><br><span class="line">Now <span class="keyword">is</span> better than never.</span><br><span class="line">Although never <span class="keyword">is</span> often better than *right* now.</span><br><span class="line"><span class="comment"># 做也许好过不做，但不假思索就动手还不如不做（动手之前要细思量）</span></span><br><span class="line">If the implementation <span class="keyword">is</span> hard to explain, it<span class="string">&#x27;s a bad idea.</span></span><br><span class="line"><span class="string">If the implementation is easy to explain, it may be a good idea.</span></span><br><span class="line"><span class="string"># 如果你无法向人描述你的方案，那肯定不是一个好方案；反之亦然（方案测评标准） </span></span><br><span class="line"><span class="string">Namespaces are one honking great idea -- let&#x27;</span>s do more of those!</span><br><span class="line"><span class="comment"># 命名空间是一种绝妙的理念，我们应当多加利用（倡导与号召）</span></span><br></pre></td></tr></table></figure><p>然后，我尝试了里面的一段demo代码：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># coding = utf-82 print (&quot;&quot;&quot;</span></span><br><span class="line">my name <span class="keyword">is</span> yufengming</span><br><span class="line">my blogs url <span class="keyword">is</span>:https://victorfengming.gitee.io/</span><br><span class="line">life <span class="keyword">is</span> so short,I need python</span><br><span class="line"><span class="string">&quot;&quot;&quot;)</span></span><br></pre></td></tr></table></figure><p>运行结果是可以成功运行的，但打印出来的结果前面，专门提及了python的设计哲学，说明，这段代码是不够简洁高效的。。。</p><p>突然明白一个道理：学习一门编程语言，一定要了解这门语言的特性。。。</p><p>其实做一件事学一门技术也一样（不限于编程语言，虽然编程语言也是一门技术、手段），要了解它的特性，才能更好的使用它，发挥它的作用！！！</p><p>引以为戒啊，兄弟</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python如何判断一个对象是函数还是方法</title>
      <link href="cp/python/python-check-function/"/>
      <url>cp/python/python-check-function/</url>
      
        <content type="html"><![CDATA[<p>在Python中，判断一个对象是否是方法有如下三种方法。</p><h2 id="1-根据call属性判断"><a name="t0"></a>1. 根据“__call__”属性判断</h2><p>有时候用python就有这么一种感悟，各种钩子函数就是通过内置的“__”属性实现，python学得好不好，就是对“__”属性理解得透彻不透彻。</p><p>python函数在调用时，一定会首先调用其相关“__call__”函数（没有空格），请参见<a href="http://blog.csdn.net/yiifaa/article/details/78035560"                                                   rel="nofollow">python总结(四)：类装饰器与方法的动态添加</a>中的用法。</p><pre class="prettyprint" name="code"><code class="language-python hljs  has-numbering"                                           onclick="mdcp.copyCode(event)" style="position: unset;">add = <span        class="hljs-keyword">lambda</span> a, b: a + b<span class="hljs-comment">#   判断成功</span><span class="hljs-keyword">if</span>(hasattr(add, <span class="hljs-string">'__call__'</span>)):        <span class="hljs-keyword">print</span> add(<span class="hljs-number">1</span>,<span            class="hljs-number">2</span>)<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul        class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li        style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li        style="color: rgb(153, 153, 153);">4</li></ul></pre><h2 id="2-利用callable判断"><a name="t1"></a>2. 利用callable判断</h2><p>这是一个据传快要废弃的方法，但是在Python 2中依旧很好用，如下：</p><pre class="prettyprint" name="code"><code class="language-python hljs  has-numbering"                                           onclick="mdcp.copyCode(event)" style="position: unset;"><span        class="hljs-comment">#   判断成功</span><span class="hljs-keyword">if</span>(callable(add)):        <span class="hljs-keyword">print</span> add(<span class="hljs-number">2</span>, <span            class="hljs-number">2</span>)<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul        class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li        style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre><h2 id="3-利用isfunction进行判断"><a name="t2"></a>3. 利用isfunction进行判断</h2><p>Python的inspect模块包含了大量的与反射、元数据相关的工具函数，isfunction就是其中一种，使用方法如下：</p><pre class="prettyprint" name="code"><code class="language-python hljs  has-numbering"                                           onclick="mdcp.copyCode(event)" style="position: unset;"><span        class="hljs-keyword">from</span> inspect <span class="hljs-keyword">import</span> isfunction<span class="hljs-comment">#   判断成功</span><span class="hljs-keyword">if</span>(isfunction(add)):    <span class="hljs-keyword">print</span> add(<span class="hljs-number">5</span>, <span class="hljs-number">5</span>)<div            class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li        style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li        style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre><h2 id="4-无效的typesmethodtype"><a name="t3"></a>4. 无效的types.MethodType</h2><p>出人意料的是types.MethodType竟然无效(版本2.7.14)，如下：</p><pre class="prettyprint" name="code"><code class="language-python hljs  has-numbering"                                           onclick="mdcp.copyCode(event)" style="position: unset;"><span        class="hljs-keyword">import</span> types<span class="hljs-comment">#   竟然无效</span><span class="hljs-keyword">if</span>(isinstance(add, types.MethodType)):    <span class="hljs-keyword">print</span> add.__name__<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul        class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li        style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li        style="color: rgb(153, 153, 153);">4</li></ul></pre><p>在这个引申过程中，还发现了一些有意思的现象，不同的function的输出结果不一样：</p><pre class="prettyprint" name="code"><code class="language-bash hljs  has-numbering" onclick="mdcp.copyCode(event)"                                           style="position: unset;">&gt;&gt;&gt; <span        class="hljs-built_in">type</span>(format)&lt;<span class="hljs-built_in">type</span> <span class="hljs-string">'builtin_function_or_method'</span>&gt;&gt;&gt;&gt; <span class="hljs-built_in">type</span>(add)&lt;<span class="hljs-built_in">type</span> <span class="hljs-string">'function'</span>&gt;<div class="hljs-button &#123;2&#125;"                                                                                                data-title="复制"></div></code><ul        class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li        style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li        style="color: rgb(153, 153, 153);">4</li></ul></pre><p>更有意思的是，type竟然无法对print进行操作，如下：</p><pre class="prettyprint" name="code"><code class="hljs haskell has-numbering" onclick="mdcp.copyCode(event)"                                           style="position: unset;">&gt;&gt;&gt; <span class="hljs-typedef"><span        class="hljs-keyword">type</span><span class="hljs-container">(<span        class="hljs-title">print</span>)</span></span>  <span class="hljs-type">File</span> <span class="hljs-string">"&lt;stdin&gt;"</span>, line <span            class="hljs-number">1</span>    <span class="hljs-typedef"><span class="hljs-keyword">type</span><span class="hljs-container">(<span            class="hljs-title">print</span>)</span></span>             ^<span class="hljs-type">SyntaxError</span>: invalid syntax<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul        class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li        style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li        style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p><strong>那print是什么？</strong></p><h2 id="结论"><a name="t4"></a>结论</h2><p>如何判断一个对象是否是方法，本文提供了3种方法，并发现了一些有意思的现象，再问一遍，print是什么？</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中@classmethod 和@staticmethod用法和区别</title>
      <link href="cp/python/python-class-decorator/"/>
      <url>cp/python/python-class-decorator/</url>
      
        <content type="html"><![CDATA[<p><code>@classsmethod</code>    类装饰器：当用此装饰器定义方法时，将类而不是类的实例作为第一个参数，这意味着可以在此方法中直接使用类的属性，而不是特定的实例的属性，因此不必进行硬编码。</p><p><code>@staticmethod</code> 静态装饰器：当用此装饰器定义方法时，不会传递类或实例作为它的参数，这意味着可以在类中放置一个函数。静态方法就是普通的函数，只是碰巧在类的定义体中，而不是在模块层定义。</p><blockquote>    <p>在《流畅的Python》中，作者对这两个装饰器的评价：classmethod 装饰器非常有用，但是我从未见过不得不用 staticmethod        的情况。如果想定义不需要与类交互的函数，那么在模块中定义就好了。有时，函数虽然从不处理类，但是函数的功能与类紧密相关，因此想把它放在近处。即便如此，在同一模块中的类前面或后面定义函数也就行了。</p></blockquote><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">class</span> <span class="token class-name">Date</span><span        class="token punctuation">(</span><span class="token builtin">object</span><span        class="token punctuation">)</span><span class="token punctuation">:</span><pre><code>&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; day&lt;span        class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; month&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span        class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; year&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span        class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;day &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; day    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;month &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; month    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;year &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; year@&lt;span class=&quot;token builtin&quot;&gt;classmethod&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;from_string&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cls&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date_as_string&lt;span        class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;    day&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; month&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; year &lt;span        class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date_as_string&lt;span        class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;split&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span        class=&quot;token string&quot;&gt;&#39;-&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    date1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cls&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;day&lt;span        class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; month&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; year&lt;span        class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; date1@&lt;span class=&quot;token builtin&quot;&gt;staticmethod&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;is_date_valid&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date_as_string&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;    day&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; month&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; year &lt;span        class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date_as_string&lt;span        class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;split&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span        class=&quot;token string&quot;&gt;&#39;-&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span        class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; day &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span        class=&quot;token number&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; month &lt;span        class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt; &lt;span        class=&quot;token keyword&quot;&gt;and&lt;/span&gt; year &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span        class=&quot;token number&quot;&gt;3999&lt;/span&gt;</code></pre><p>date2 <span class="token operator">=</span> Date<span class="token punctuation">.</span>from_string<span            class="token punctuation">(</span><span class="token string">‘11-09-2012’</span><span            class="token punctuation">)</span><br>is_date <span class="token operator">=</span> Date<span class="token punctuation">.</span>is_date_valid<span            class="token punctuation">(</span><span class="token string">‘11-09-2012’</span><span            class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>使用静态方法写基类，注意静态方法使用了实例的硬编码。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">class</span> <span class="token class-name">Date</span><span        class="token punctuation">:</span>  <span class="token keyword">def</span> <span class="token function">__init__</span><span            class="token punctuation">(</span>self<span class="token punctuation">,</span> month<span            class="token punctuation">,</span> day<span class="token punctuation">,</span> year<span            class="token punctuation">)</span><span class="token punctuation">:</span>    self<span class="token punctuation">.</span>month <span class="token operator">=</span> month    self<span class="token punctuation">.</span>day   <span class="token operator">=</span> day    self<span class="token punctuation">.</span>year  <span class="token operator">=</span> year<p>  <span class="token keyword">def</span> <span class="token function">display</span><span            class="token punctuation">(</span>self<span class="token punctuation">)</span><span            class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token string">“&#123;0&#125;-&#123;1&#125;-&#123;2&#125;”</span><span            class="token punctuation">.</span><span class="token builtin">format</span><span            class="token punctuation">(</span>self<span class="token punctuation">.</span>month<span            class="token punctuation">,</span> self<span class="token punctuation">.</span>day<span            class="token punctuation">,</span> self<span class="token punctuation">.</span>year<span            class="token punctuation">)</span></p><p>  @<span class="token builtin">staticmethod</span><br>  <span class="token keyword">def</span> <span class="token function">millenium</span><span            class="token punctuation">(</span>month<span class="token punctuation">,</span> day<span            class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> Date<span class="token punctuation">(</span>month<span            class="token punctuation">,</span> day<span class="token punctuation">,</span> <span            class="token number">2000</span><span class="token punctuation">)</span></p><p>new_year <span class="token operator">=</span> Date<span class="token punctuation">(</span><span            class="token number">1</span><span class="token punctuation">,</span> <span            class="token number">1</span><span class="token punctuation">,</span> <span            class="token number">2013</span><span class="token punctuation">)</span>               <span            class="token comment"># Creates a new Date object</span><br>millenium_new_year <span class="token operator">=</span> Date<span class="token punctuation">.</span>millenium<span            class="token punctuation">(</span><span class="token number">1</span><span            class="token punctuation">,</span> <span class="token number">1</span><span            class="token punctuation">)</span> <span class="token comment"># also creates a Date object. </span></p><p><span class="token comment"># Proof:</span><br>new_year<span class="token punctuation">.</span>display<span class="token punctuation">(</span><span            class="token punctuation">)</span>           <span class="token comment"># “1-1-2013”</span><br>millenium_new_year<span class="token punctuation">.</span>display<span class="token punctuation">(</span><span            class="token punctuation">)</span> <span class="token comment"># “1-1-2000”</span></p><p><span class="token builtin">isinstance</span><span class="token punctuation">(</span>new_year<span            class="token punctuation">,</span> Date<span class="token punctuation">)</span> <span            class="token comment"># True</span><br><span class="token builtin">isinstance</span><span class="token punctuation">(</span>millenium_new_year<span            class="token punctuation">,</span> Date<span class="token punctuation">)</span> <span            class="token comment"># True</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>继承之后，millenium方法就用不了了。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token keyword">class</span> <span class="token class-name">DateTime</span><span        class="token punctuation">(</span>Date<span class="token punctuation">)</span><span        class="token punctuation">:</span>  <span class="token keyword">def</span> <span class="token function">display</span><span            class="token punctuation">(</span>self<span class="token punctuation">)</span><span            class="token punctuation">:</span>      <span class="token keyword">return</span> <span class="token string">"&#123;0&#125;-&#123;1&#125;-&#123;2&#125; - 00:00:00PM"</span><span            class="token punctuation">.</span><span class="token builtin">format</span><span            class="token punctuation">(</span>self<span class="token punctuation">.</span>month<span            class="token punctuation">,</span> self<span class="token punctuation">.</span>day<span            class="token punctuation">,</span> self<span class="token punctuation">.</span>year<span            class="token punctuation">)</span><p>datetime1 <span class="token operator">=</span> DateTime<span class="token punctuation">(</span><span            class="token number">10</span><span class="token punctuation">,</span> <span            class="token number">10</span><span class="token punctuation">,</span> <span            class="token number">1990</span><span class="token punctuation">)</span><br>datetime2 <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>millenium<span            class="token punctuation">(</span><span class="token number">10</span><span            class="token punctuation">,</span> <span class="token number">10</span><span            class="token punctuation">)</span></p><p><span class="token builtin">isinstance</span><span class="token punctuation">(</span>datetime1<span            class="token punctuation">,</span> DateTime<span class="token punctuation">)</span> <span            class="token comment"># True</span><br><span class="token builtin">isinstance</span><span class="token punctuation">(</span>datetime2<span            class="token punctuation">,</span> DateTime<span class="token punctuation">)</span> <span            class="token comment"># False</span></p><p>datetime1<span class="token punctuation">.</span>display<span class="token punctuation">(</span><span            class="token punctuation">)</span> <span            class="token comment"># returns “10-10-1990 - 00:00:00PM”</span><br>datetime2<span class="token punctuation">.</span>display<span class="token punctuation">(</span><span            class="token punctuation">)</span> <span class="token comment"># returns “10-10-2000” because it’s not a DateTime object but a Date object.</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>改成类方法，</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token decorator annotation punctuation">@classmethod</span><span class="token keyword">def</span> <span class="token function">millenium</span><span            class="token punctuation">(</span>cls<span class="token punctuation">,</span> month<span            class="token punctuation">,</span> day<span class="token punctuation">)</span><span            class="token punctuation">:</span>    <span class="token keyword">return</span> cls<span class="token punctuation">(</span>month<span            class="token punctuation">,</span> day<span class="token punctuation">,</span> <span            class="token number">2000</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>就正确了</p><pre class="line-numbers  language-python"><code class="python  language-python">datetime1 <span        class="token operator">=</span> DateTime<span class="token punctuation">(</span><span        class="token number">10</span><span        class="token punctuation">,</span> <span class="token number">10</span><span        class="token punctuation">,</span> <span class="token number">1990</span><span        class="token punctuation">)</span>datetime2 <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>millenium<span            class="token punctuation">(</span><span class="token number">10</span><span            class="token punctuation">,</span> <span class="token number">10</span><span            class="token punctuation">)</span><p><span class="token builtin">isinstance</span><span class="token punctuation">(</span>datetime1<span            class="token punctuation">,</span> DateTime<span class="token punctuation">)</span> <span            class="token comment"># True</span><br><span class="token builtin">isinstance</span><span class="token punctuation">(</span>datetime2<span            class="token punctuation">,</span> DateTime<span class="token punctuation">)</span> <span            class="token comment"># True</span></p><p>datetime1<span class="token punctuation">.</span>display<span class="token punctuation">(</span><span            class="token punctuation">)</span> <span class="token comment"># “10-10-1990 - 00:00:00PM”</span><br>datetime2<span class="token punctuation">.</span>display<span class="token punctuation">(</span><span            class="token punctuation">)</span> <span class="token comment"># “10-10-2000 - 00:00:00PM”</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>代码来自下面的链接，答的很赞：<br>    <a href="https://stackoverflow.com/questions/12179271/meaning-of-classmethod-and-staticmethod-for-beginner/"       target="_blank" rel="nofollow">https://stackoverflow.com/questions/12179271/meaning-of-classmethod-and-staticmethod-for-beginner/</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> decorator </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python之可变数据类型和不可变数据类型</title>
      <link href="cp/python/python-data-type/"/>
      <url>cp/python/python-data-type/</url>
      
        <content type="html"><![CDATA[<p>说白了:就看内存地址和数据的值能不能对应上</p><p>可变类型：在id(内存地址)不变的情况下，value（值）可以变，则称为可变类型</p><p>不可变类型：value(值)一旦改变，id（内存地址）也改变，则称为不可变类型（id变，意味着创建了新的内存空间）</p><p>不可变数据类型：Number（数字）、String（字符串）、Tuple（元组）；<br>可变数据类型：List（列表）、Dictionary（字典）、Set（集合）</p><p>我们可以使用：id()的方式进行查看数据的内存地址， 从对象内存地址方向来说：<br>可变数据类型：在内存地址不变的情况下，值可改变（列表和字典是可变类型，但是字典中的 key 值必须是不可变类型）<br>不可变数据类型：内存地址改变，值也跟着改变。（数字，字符串，布尔类型，都是不可变类型）可以通过 id() 方法进行内存地址的检测。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中的装饰器:Decorator</title>
      <link href="cp/python/python-decorator/"/>
      <url>cp/python/python-decorator/</url>
      
        <content type="html"><![CDATA[<article class="_2rhmJa"><h2>理解Python装饰器(Decorator)</h2>    <p>Python装饰器看起来类似Java中的注解，然鹅和注解并不相同，不过同样能够实现面向切面编程。</p>    <p>想要理解Python中的装饰器，不得不先理解闭包（closure）这一概念。</p>    <h3>闭包</h3>    <p>看看维基百科中的解释：</p>    <blockquote>        <p>在计算机科学中，闭包（英语：Closure），又称词法闭包（Lexical Closure）或函数闭包（function            closures），是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在，即使已经离开了创造它的环境也不例外。</p>    </blockquote>    <p>官方的解释总是不说人话，but--talk is cheap，show me the code:</p>    <pre class="line-numbers  language-python"><code class="  language-python"><span class="token comment"># print_msg是外围函数</span><span class="token keyword">def</span> <span class="token function">print_msg</span><span                class="token punctuation">(</span><span class="token punctuation">)</span><span                class="token punctuation">:</span>    msg <span class="token operator">=</span> <span class="token string">"I'm closure"</span><pre><code>&lt;span class=&quot;token comment&quot;&gt;# printer是嵌套函数&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printer&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span            class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span            class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; printer</code></pre><p><span class="token comment"># 这里获得的就是一个闭包</span><br>closure <span class="token operator">=</span> print_msg<span class="token punctuation">(</span><span                class="token punctuation">)</span><br><span class="token comment"># 输出 I’m closure</span><br>closure<span class="token punctuation">(</span><span class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button            class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg            viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"            fill="currentColor" aria-hidden="true"><path            d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><br>    <p><code>msg</code>是一个局部变量，在<code>print_msg</code>函数执行之后应该就不会存在了。但是嵌套函数引用了这个变量，将这个局部变量封闭在了嵌套函数中，这样就形成了一个闭包。</p><br>    <p>结合这个例子再看维基百科的解释，就清晰明了多了。闭包就是引用了自有变量的函数，这个函数保存了执行的上下文，可以脱离原本的作用域独立存在。</p><br>    <p>下面来看看Python中的装饰器。</p><br>    <h3>装饰器</h3><br>    <p>一个普通的装饰器一般是这样：</p><br>    <pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">import</span> functools</p><p><span class="token keyword">def</span> <span class="token function">log</span><span class="token punctuation">(</span>func<span                class="token punctuation">)</span><span class="token punctuation">:</span><br>    @functools<span class="token punctuation">.</span>wraps<span class="token punctuation">(</span>func<span                class="token punctuation">)</span><br>    <span class="token keyword">def</span> <span class="token function">wrapper</span><span                class="token punctuation">(</span><span class="token operator"><em></span>args<span                class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span                class="token punctuation">)</span><span class="token punctuation">:</span><br>        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">‘call %s():’</span> <span                class="token operator">%</span> func<span class="token punctuation">.</span><strong>name</strong><span                class="token punctuation">)</span><br>        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">‘args = &#123;&#125;’</span><span                class="token punctuation">.</span><span class="token builtin">format</span><span                class="token punctuation">(</span><span class="token operator"></em></span>args<span                class="token punctuation">)</span><span class="token punctuation">)</span><br>        <span class="token keyword">return</span> func<span class="token punctuation">(</span><span                class="token operator">*</span>args<span class="token punctuation">,</span> <span                class="token operator">**</span>kwargs<span class="token punctuation">)</span></p><pre><code>&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; wrapper</code></pre><p><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button            class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg            viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"            fill="currentColor" aria-hidden="true"><path            d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><br>    <p>这样就定义了一个打印出方法名及其参数的装饰器。</p><br>    <p>调用之：</p><br>    <pre class="line-numbers  language-python"><code class="  language-python"><span            class="token decorator annotation punctuation">@log</span><br><span class="token keyword">def</span> <span class="token function">test</span><span class="token punctuation">(</span>p<span                class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>test<span class="token punctuation">.</span><strong>name</strong> <span                class="token operator">+</span> <span class="token string">" param: "</span> <span                class="token operator">+</span> p<span class="token punctuation">)</span></p><p>test<span class="token punctuation">(</span><span class="token string">“I’m a param”</span><span                class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code><button            class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg            viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"            fill="currentColor" aria-hidden="true"><path            d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><br>    <p>输出：</p><br>    <pre class="line-numbers  language-bash"><code class="  language-bash">call test():<br>args = I'm a param<br>test param: I'm a param<br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button            class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg            viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"            fill="currentColor" aria-hidden="true"><path            d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><br>    <p>装饰器在使用时，用了<code>@</code>语法，让人有些困扰。其实，装饰器只是个方法，与下面的调用方式没有区别：</p><br>    <pre class="line-numbers  language-bash"><code class="  language-bash">def test(p):<br>    print(test.<strong>name</strong> + " param: " + p)</p><p>wrapper = log(test)<br>wrapper(“I’m a param”)<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code><button            class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg            viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"            fill="currentColor" aria-hidden="true"><path            d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><br>    <p><code>@</code>语法只是将函数传入装饰器函数，并无神奇之处。</p><br>    <p>值得注意的是<code>@functools.wraps(func)</code>，这是python提供的装饰器。它能把原函数的元信息拷贝到装饰器里面的 func 函数中。函数的元信息包括docstring、<strong>name</strong>、参数列表等等。可以尝试去除<code>@functools.wraps(func)</code>，你会发现<code>test.<strong>name</strong></code>的输出变成了wrapper。<br>    </p><br>    <h3>带参数的装饰器</h3><br>    <p>装饰器允许传入参数，一个携带了参数的装饰器将有三层函数，如下所示：</p><br>    <pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">import</span> functools</p><p><span class="token keyword">def</span> <span class="token function">log_with_param</span><span                class="token punctuation">(</span>text<span class="token punctuation">)</span><span                class="token punctuation">:</span><br>    <span class="token keyword">def</span> <span class="token function">decorator</span><span class="token punctuation">(</span>func<span                class="token punctuation">)</span><span class="token punctuation">:</span><br>        @functools<span class="token punctuation">.</span>wraps<span class="token punctuation">(</span>func<span                class="token punctuation">)</span><br>        <span class="token keyword">def</span> <span class="token function">wrapper</span><span                class="token punctuation">(</span><span class="token operator"><em></span>args<span                class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span                class="token punctuation">)</span><span class="token punctuation">:</span><br>            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">‘call %s():’</span> <span                class="token operator">%</span> func<span class="token punctuation">.</span><strong>name</strong><span                class="token punctuation">)</span><br>            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">‘args = &#123;&#125;’</span><span                class="token punctuation">.</span><span class="token builtin">format</span><span                class="token punctuation">(</span><span class="token operator"></em></span>args<span                class="token punctuation">)</span><span class="token punctuation">)</span><br>            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">‘log_param = &#123;&#125;’</span><span                class="token punctuation">.</span><span class="token builtin">format</span><span                class="token punctuation">(</span>text<span class="token punctuation">)</span><span                class="token punctuation">)</span><br>            <span class="token keyword">return</span> func<span class="token punctuation">(</span><span                class="token operator">*</span>args<span class="token punctuation">,</span> <span                class="token operator">**</span>kwargs<span class="token punctuation">)</span></p><pre><code>    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; wrapper&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; decorator</code></pre><p>@log_with_param<span class="token punctuation">(</span><span class="token string">“param”</span><span                class="token punctuation">)</span><br><span class="token keyword">def</span> <span class="token function">test_with_param</span><span                class="token punctuation">(</span>p<span class="token punctuation">)</span><span                class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>test_with_param<span                class="token punctuation">.</span><strong>name</strong><span class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button            class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg            viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"            fill="currentColor" aria-hidden="true"><path            d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><br>    <p>看到这个代码是不是又有些疑问，内层的decorator函数的参数func是怎么传进去的？和上面一般的装饰器不大一样啊。</p><br>    <p>其实道理是一样的，将其<code>@</code>语法去除，恢复函数调用的形式一看就明白了：</p><br>    <pre class="line-numbers  language-bash"><code class="  language-bash"># 传入装饰器的参数，并接收返回的decorator函数<br>decorator = log_with_param("param")</p><h1 id="传入test-with-param函数"><a href="#传入test-with-param函数" class="headerlink" title="传入test_with_param函数"></a>传入test_with_param函数</h1><p>wrapper = decorator(test_with_param)</p><h1 id="调用装饰器函数"><a href="#调用装饰器函数" class="headerlink" title="调用装饰器函数"></a>调用装饰器函数</h1><p>wrapper(“I’m a param”)<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button            class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg            viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"            fill="currentColor" aria-hidden="true"><path            d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><br>    <p>输出结果与正常使用装饰器相同：</p><br>    <pre class="line-numbers  language-rust"><code class="  language-rust">call <span class="token function">test_with_param</span><span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span><br>args <span class="token operator">=</span> I<span class="token lifetime-annotation symbol">'m</span> a param<br>log_param <span class="token operator">=</span> param<br>test_with_param<br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code><button            class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg            viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"            fill="currentColor" aria-hidden="true"><path            d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><br>    <p>至此，装饰器这个有点费解的特性也没什么神秘了。</p><br>    <p>装饰器这一语法体现了Python中函数是第一公民，函数是对象、是变量，可以作为参数、可以是返回值，非常的灵活与强大。</p><br>    <p>Python中引入了很多函数式编程的特性，需要好好学习与体会。</p></p></article>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> decorator </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python中装饰器详解</title>
      <link href="cp/python/python-decorator2/"/>
      <url>cp/python/python-decorator2/</url>
      
        <content type="html"><![CDATA[<p>在python中,有一个这么东西</p><p>开放封闭原则</p><p>闭包</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> decorator </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中的docstring</title>
      <link href="cp/python/python-docstring/"/>
      <url>cp/python/python-docstring/</url>
      
        <content type="html"><![CDATA[<div style="line-height:28px;word-wrap:break-word">    <h1 style="color:#903;line-height:36px;margin-bottom:4px">使用Python的docstring</h1>    <p style="color:#aaa">        2017年8月25日<span> / </span>11,653次阅读<br><a style="color:#903" target="_blank"                                                  href="https://www.maixj.net/tag/py">Python</a></p><pre><code>&lt;div&gt;    &lt;div id=&quot;wz&quot;&gt;&lt;p&gt;程序员一直以来都有一个烦恼，他们只想写代码，不想写文档。他们说：代码就表达了我的思想和灵魂。&lt;/p&gt;        &lt;p&gt;小公司相对随意一些，可以先写代码调试，但是最后老板害怕程序员离职造成“青黄不接”，还是会要求补上文档。大公司要求更高，要先写文档，评审通过，然后再开始编码。有的程序员整天都在写文档，苦不堪言。&lt;/p&gt;        &lt;p&gt;Python提出了一个方案，叫docstring，来试图解决这个问题。即编写代码，同时也能写出文档，保持代码和文档的一致。&lt;/p&gt;        &lt;p&gt;            Python提出的这个方案其实并不新鲜，docstring说白了就是一堆代码中的注释。任何编程语言都有注释的好不好！！不过，Python的docstring可以通过help函数直接输出一份有格式的文档，这个就厉害了。代码写完，注释写完，一个help调用，就有文档看了。&lt;/p&gt;        &lt;p&gt;&amp;nbsp;&lt;/p&gt;        &lt;p&gt;&lt;strong&gt;docstring可以写在三个地方：模块或包，对象，函数。&lt;/strong&gt;&lt;/p&gt;        &lt;p&gt;（以下示例使用著名的requests包）&lt;/p&gt;        &lt;p&gt;&amp;nbsp;&lt;/p&gt;        &lt;p&gt;对于模块，docstring就是在模块文件的最前面，如下示例：&lt;/p&gt;        &lt;pre&gt;&lt;code class=&quot;python hljs&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# -*- coding: utf-8 -*-&lt;/span&gt;</code></pre><p><span class="hljs-string">“””<br>requests.api</p><p>~~~~~~~~~~~~</p><p>This module implements the Requests API.</p><p>:copyright: (c) 2012 by Kenneth Reitz.<br>:license: Apache2, see LICENSE for more details.<br>“””</span></p><p><span class="hljs-keyword">from</span> . <span class="hljs-keyword">import</span> sessions</code></pre><br>            <p><span style="color: #ff0000;"><strong>docstring使用三个双引号（”），triple double quote for docstring，这是PEP0257里的约定。</strong></span><br>            </p><br>            <p>&nbsp;</p><br>            <p>对于包，docstring就是在package的__init__.py这个文件的任何语句的前面（<strong>docstring的前面还可以有#注释</strong>），如下示例：</p><br>            <pre><code class="python hljs"><span class="hljs-comment"># -<em>- coding: utf-8 -</em>-</span></p><p><span class="hljs-comment">#   <strong></span><br><span class="hljs-comment">#  /</strong>)  _  _     _   _ _/   _</span><br><span class="hljs-comment"># / (   (- (/ (/ (- _)  /  _)</span><br><span class="hljs-comment">#          /</span></p><p><span class="hljs-string">“””<br>Requests HTTP Library</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">Requests is an HTTP library, written in Python, for human beings. Basic GET</span><br><span class="line">usage:</span><br><span class="line"></span><br><span class="line">   &gt;&gt;&gt; import requests</span><br><span class="line">   &gt;&gt;&gt; r &#x3D; requests.get(&#39;https:&#x2F;&#x2F;www.python.org&#39;)</span><br><span class="line">   &gt;&gt;&gt; r.status_code</span><br><span class="line">   200</span><br><span class="line">   &gt;&gt;&gt; &#39;Python is a programming language&#39; in r.content</span><br><span class="line">   True</span><br><span class="line"></span><br><span class="line">&lt;span class&#x3D;&quot;hljs-meta&quot;&gt;... &lt;&#x2F;span&gt;or POST:</span><br><span class="line"></span><br><span class="line">   &gt;&gt;&gt; payload &#x3D; dict(key1&#x3D;&#39;value1&#39;, key2&#x3D;&#39;value2&#39;)</span><br><span class="line">   &gt;&gt;&gt; r &#x3D; requests.post(&#39;http:&#x2F;&#x2F;httpbin.org&#x2F;post&#39;, data&#x3D;payload)</span><br><span class="line">   &gt;&gt;&gt; print(r.text)</span><br><span class="line">   &#123;</span><br><span class="line">     ...</span><br><span class="line">     &quot;form&quot;: &#123;</span><br><span class="line">       &quot;key2&quot;: &quot;value2&quot;,</span><br><span class="line">       &quot;key1&quot;: &quot;value1&quot;</span><br><span class="line">     &#125;,</span><br><span class="line">     ...</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">The other HTTP methods are supported - see &#96;requests.api&#96;. Full documentation</span><br><span class="line">is at &lt;http:&#x2F;&#x2F;python-requests.org&gt;.</span><br><span class="line"></span><br><span class="line">:copyright: (c) 2017 by Kenneth Reitz.</span><br><span class="line">:license: Apache 2.0, see LICENSE for more details.</span><br><span class="line">&quot;&quot;&quot;&lt;&#x2F;span&gt;</span><br><span class="line"></span><br><span class="line">&lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;import&lt;&#x2F;span&gt; urllib3&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</span><br><span class="line">            &lt;p&gt;&amp;nbsp;&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;p&gt;对于函数，docstring就是在函数定义的最前面，如下示例：&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;pre&gt;&lt;code class&#x3D;&quot;python hljs&quot;&gt;&lt;span class&#x3D;&quot;hljs-function&quot;&gt;&lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;def&lt;&#x2F;span&gt; &lt;span</span><br><span class="line">                    class&#x3D;&quot;hljs-title&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class&#x3D;&quot;hljs-params&quot;&gt;(url, params&#x3D;None, **kwargs)&lt;&#x2F;span&gt;:&lt;&#x2F;span&gt;</span><br><span class="line">    &lt;span class&#x3D;&quot;hljs-string&quot;&gt;r&quot;&quot;&quot;Sends a GET request.</span><br><span class="line"></span><br><span class="line">    :param url: URL for the new :class:&#96;Request&#96; object.</span><br><span class="line">    :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:&#96;Request&#96;.</span><br><span class="line">    :param \*\*kwargs: Optional arguments that &#96;&#96;request&#96;&#96; takes.</span><br><span class="line">    :return: :class:&#96;Response &lt;Response&gt;&#96; object</span><br><span class="line">    :rtype: requests.Response</span><br><span class="line">    &quot;&quot;&quot;&lt;&#x2F;span&gt;</span><br><span class="line"></span><br><span class="line">    kwargs.setdefault(&lt;span class&#x3D;&quot;hljs-string&quot;&gt;&#39;allow_redirects&#39;&lt;&#x2F;span&gt;, &lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;True&lt;&#x2F;span&gt;)</span><br><span class="line">    &lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;return&lt;&#x2F;span&gt; request(&lt;span class&#x3D;&quot;hljs-string&quot;&gt;&#39;get&#39;&lt;&#x2F;span&gt;, url, params&#x3D;params, **kwargs)&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</span><br><span class="line">            &lt;p&gt;&lt;strong&gt;注意上例的三个双引号前有个r，r是raw的意思，表示这个字符串里面的\就是它自己，不是用来转意的。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;p&gt;&amp;nbsp;&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;p&gt;对于对象定义，docstring就是在class定义的最前面，如下示例：&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;pre&gt;&lt;code class&#x3D;&quot;python hljs&quot;&gt;&lt;span class&#x3D;&quot;hljs-class&quot;&gt;&lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;class&lt;&#x2F;span&gt; &lt;span</span><br><span class="line">                    class&#x3D;&quot;hljs-title&quot;&gt;Timeout&lt;&#x2F;span&gt;&lt;span class&#x3D;&quot;hljs-params&quot;&gt;(RequestException)&lt;&#x2F;span&gt;:&lt;&#x2F;span&gt;</span><br><span class="line">    &lt;span class&#x3D;&quot;hljs-string&quot;&gt;&quot;&quot;&quot;The request timed out.</span><br><span class="line"></span><br><span class="line">    Catching this error will catch both</span><br><span class="line">    :exc:&#96;~requests.exceptions.ConnectTimeout&#96; and</span><br><span class="line">    :exc:&#96;~requests.exceptions.ReadTimeout&#96; errors.</span><br><span class="line">    &quot;&quot;&quot;&lt;&#x2F;span&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&lt;span class&#x3D;&quot;hljs-class&quot;&gt;&lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;class&lt;&#x2F;span&gt; &lt;span class&#x3D;&quot;hljs-title&quot;&gt;ConnectTimeout&lt;&#x2F;span&gt;&lt;span</span><br><span class="line">        class&#x3D;&quot;hljs-params&quot;&gt;(ConnectionError, Timeout)&lt;&#x2F;span&gt;:&lt;&#x2F;span&gt;</span><br><span class="line">    &lt;span class&#x3D;&quot;hljs-string&quot;&gt;&quot;&quot;&quot;The request timed out while trying to connect to the remote server.</span><br><span class="line"></span><br><span class="line">    Requests that produced this error are safe to retry.</span><br><span class="line">    &quot;&quot;&quot;&lt;&#x2F;span&gt;</span><br><span class="line">&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</span><br><span class="line">            &lt;p&gt;&amp;nbsp;&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;p&gt;还有一种单行docstring的写法，如下：&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;pre&gt;&lt;code class&#x3D;&quot;python hljs&quot;&gt;&lt;span class&#x3D;&quot;hljs-function&quot;&gt;&lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;def&lt;&#x2F;span&gt; &lt;span</span><br><span class="line">                    class&#x3D;&quot;hljs-title&quot;&gt;getStartLink&lt;&#x2F;span&gt;&lt;span class&#x3D;&quot;hljs-params&quot;&gt;()&lt;&#x2F;span&gt;:&lt;&#x2F;span&gt;</span><br><span class="line">    &lt;span class&#x3D;&quot;hljs-string&quot;&gt;&quot;&quot;&quot;get start link&quot;&quot;&quot;&lt;&#x2F;span&gt;</span><br><span class="line">    startLink &#x3D; str()</span><br><span class="line"></span><br><span class="line">    &lt;span class&#x3D;&quot;hljs-comment&quot;&gt;# get start link value&lt;&#x2F;span&gt;</span><br><span class="line">    &lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;if&lt;&#x2F;span&gt; __name__ &#x3D;&#x3D; &lt;span class&#x3D;&quot;hljs-string&quot;&gt;&quot;__main__&quot;&lt;&#x2F;span&gt;:&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</span><br><span class="line">            &lt;p&gt;&amp;nbsp;&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;p&gt;Python builtin的help函数主要是在交互模式下使用，在交互模式下，使用help，就能够看到文档中的这些被称为docstring的注释，被一种良好的格式显示出来。&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;p&gt;在调整代码的时候，维护注释，维护docstring，进而保持代码和文档（help函数的输出）一致，麦新杰认为是一种简化的思想。docstring不是强制的，如果不写，help函数的输出就是空空的。&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;p&gt;下面是help(requests)的输出：&lt;&#x2F;p&gt;</span><br><span class="line">            &lt;pre&gt;&lt;code class&#x3D;&quot;python hljs&quot;&gt;&gt;&gt;&gt;</span><br><span class="line">&lt;span class&#x3D;&quot;hljs-meta&quot;&gt;&gt;&gt;&gt; &lt;&#x2F;span&gt;&lt;span class&#x3D;&quot;hljs-keyword&quot;&gt;import&lt;&#x2F;span&gt; requests</span><br><span class="line">&lt;span class&#x3D;&quot;hljs-meta&quot;&gt;&gt;&gt;&gt; &lt;&#x2F;span&gt;help(requests)</span><br><span class="line">Help on package requests:</span><br><span class="line"></span><br><span class="line">NAME</span><br><span class="line">    requests</span><br><span class="line"></span><br><span class="line">DESCRIPTION</span><br><span class="line">    Requests HTTP Library</span><br></pre></td></tr></table></figure><pre><code>Requests &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; an HTTP library, written &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; Python, &lt;span                    class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; human beings. Basic GETusage:   &amp;gt;&amp;gt;&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; requests   &amp;gt;&amp;gt;&amp;gt; r = requests.get(&lt;span class=&quot;hljs-string&quot;&gt;&#39;https://www.python.org&#39;&lt;/span&gt;)   &amp;gt;&amp;gt;&amp;gt; r.status_code   &lt;span class=&quot;hljs-number&quot;&gt;200&lt;/span&gt;   &amp;gt;&amp;gt;&amp;gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;Python is a programming language&#39;&lt;/span&gt; &lt;span                    class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; r.content   &lt;span class=&quot;hljs-keyword&quot;&gt;True&lt;/span&gt;... &lt;span class=&quot;hljs-keyword&quot;&gt;or&lt;/span&gt; POST:   &amp;gt;&amp;gt;&amp;gt; payload = dict(key1=&lt;span class=&quot;hljs-string&quot;&gt;&#39;value1&#39;&lt;/span&gt;, key2=&lt;span class=&quot;hljs-string&quot;&gt;&#39;value2&#39;&lt;/span&gt;)   &amp;gt;&amp;gt;&amp;gt; r = requests.post(&lt;span class=&quot;hljs-string&quot;&gt;&#39;http://httpbin.org/post&#39;&lt;/span&gt;, data=payload)   &amp;gt;&amp;gt;&amp;gt; print(r.text)   &#123;     ...     &lt;span class=&quot;hljs-string&quot;&gt;&quot;form&quot;&lt;/span&gt;: &#123;       &lt;span class=&quot;hljs-string&quot;&gt;&quot;key2&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;value2&quot;&lt;/span&gt;,       &lt;span class=&quot;hljs-string&quot;&gt;&quot;key1&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;value1&quot;&lt;/span&gt;     &#125;,     ...   &#125;The other HTTP methods are supported - see `requests.api`. Full documentatio</code></pre><p>n<br>    <span class="hljs-keyword">is</span> at &lt;<a href="http://python-requests.org/">http://python-requests.org</a>&gt;.</p><pre><code>:copyright: (c) &lt;span class=&quot;hljs-number&quot;&gt;2017&lt;/span&gt; by Kenneth Reitz.:license: Apache &lt;span class=&quot;hljs-number&quot;&gt;2.0&lt;/span&gt;, see LICENSE &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; more details.</code></pre><p>PACKAGE CONTENTS<br>    <strong>version</strong><br>    <em>internal_utils<br>    adapters<br>    api<br>    auth</code></pre><br>            <p>看description部分，这就是写requests包的__init</em>_.py文档中的docstring。</p><br>            <p>而且还可以看出，help函数不仅输出docstring，还有一些其它的格式化的输出信息，非常handy呀。</p><br>            <p>&nbsp;</p><br>            <p>专业的Python docstring文档，请参考<a href="https://www.python.org/dev/peps/pep-0257/" target="_blank"                                           rel="noopener">PEP257</a></p><br>            <p>您可能要先看一下：<a href="https://www.maixj.net/ict/python-pep-13746" target="_blank"                           rel="noopener">什么是PEP文档？</a></p><br>            <p>&nbsp;</p><br>            <p>Python这种语言简单易学，有个原因就是它将一些复杂的事情简化了，比如非强制的docstring，比如强制缩进。</p><br>        </div><br>    </div></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python 中None，is和==的深入探讨</title>
      <link href="cp/python/python-equal/"/>
      <url>cp/python/python-equal/</url>
      
        <content type="html"><![CDATA[<p>原文链接:<a href="https://www.jianshu.com/p/627232777efd">https://www.jianshu.com/p/627232777efd</a></p><hr><p>注： 运行环境：python3.6.6，win10，64位</p><h2>1. None</h2><p>None是python中的一个特殊的常量，表示一个空的对象，空值是python中的一个特殊值。数据为空并不代表是空对象，例如[],''等都不是None。None和任何对象比较返回值都是False，除了自己。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> L<span class="token operator">=</span><span        class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> L <span            class="token keyword">is</span> <span class="token boolean">None</span><span class="token boolean">False</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> L<span            class="token operator">=</span><span class="token string">''</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> L <span            class="token keyword">is</span> <span class="token boolean">None</span><span class="token boolean">False</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>None有自己的数据类型NontType，你可以将None赋值给任意对象，但是不能创建一个NoneType对象。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token builtin">type</span><span        class="token punctuation">(</span><span class="token boolean">None</span><span        class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token keyword">class</span> <span            class="token string">'NoneType'</span><span class="token operator">&gt;</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> n<span            class="token operator">=</span>NoneType<span class="token punctuation">(</span><span            class="token punctuation">)</span>Traceback <span class="token punctuation">(</span>most recent call last<span class="token punctuation">)</span><span            class="token punctuation">:</span>  File <span class="token string">"&lt;input&gt;"</span><span class="token punctuation">,</span> line <span            class="token number">1</span><span class="token punctuation">,</span> <span            class="token keyword">in</span> <span class="token operator">&lt;</span>module<span            class="token operator">&gt;</span>NameError<span class="token punctuation">:</span> name <span class="token string">'NoneType'</span> <span            class="token keyword">is</span> <span class="token keyword">not</span> defined<span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><h2>2.False</h2><p>需要注意一点：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> a<span class="token operator">=</span><span        class="token boolean">False</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token keyword">not</span> a<span class="token boolean">True</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>python中数据为空的对象在判断时的结果都为False，其中None，False，0，[]，""，{}，()都相当于False，即<code>not None == not False == not '' == not 0    == not [] == not &#123;&#125; == not ()</code>。</p><h2>3. is 和 ==</h2><p>is表示的是对象标识符，用来检查对象的标识符是否一致，即两个对象在内存中的地址是否一致。在使用 <code>a is b</code> 的时候，相当于<code>id(a)==id(b)</code>。<br>    ==表示两个对象是否相等，相当于调用<code>__eq__()</code>方法，即'a==b' ==&gt; <code>a.__eq__(b)</code>。</p><h2>4. Python里和None比较时，为什么是 is None 而不是 == None</h2><p>因为None在Python里是个单例对象，一个变量如果是None，它一定和None指向同一个内存地址。</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> a<span class="token operator">=</span><span        class="token boolean">None</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> b<span            class="token operator">=</span><span class="token boolean">None</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> <span            class="token builtin">id</span><span class="token punctuation">(</span>a<span            class="token punctuation">)</span><span            class="token operator">==</span><span class="token builtin">id</span><span            class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token boolean">True</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><p>is None是判断两个对象在内存中的地址是否一致，== None背后调用的是<strong>eq</strong>，而<strong>eq</strong>可以被重载，下面是一个 is not None但 ==    None的例子：</p><pre class="line-numbers  language-python"><code class="python  language-python"><span        class="token operator">&gt;&gt;</span><span        class="token operator">&gt;</span> <span class="token keyword">class</span> <span        class="token class-name">test</span><span        class="token punctuation">(</span><span class="token punctuation">)</span><span        class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>     <span            class="token keyword">def</span> <span class="token function">__eq__</span><span            class="token punctuation">(</span>self<span class="token punctuation">,</span>other<span            class="token punctuation">)</span><span class="token punctuation">:</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>         <span            class="token keyword">return</span> <span class="token boolean">True</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> t<span            class="token operator">=</span>test<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> t <span            class="token keyword">is</span> <span class="token boolean">None</span><span class="token boolean">False</span><span class="token operator">&gt;&gt;</span><span class="token operator">&gt;</span> t <span            class="token operator">==</span> <span class="token boolean">None</span><span class="token boolean">True</span><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre><h2>5. 参考资料</h2><ul>    <li><a href="https://blog.csdn.net/Primeprime/article/details/77186109" target="_blank" rel="nofollow">https://blog.csdn.net/Primeprime/article/details/77186109</a>    </li>    <li><a href="https://www.jianshu.com/p/1cc3282bfe29" target="_blank">https://www.jianshu.com/p/1cc3282bfe29</a>    </li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>谈谈对Python和其他语言区别</title>
      <link href="cp/python/python-feature/"/>
      <url>cp/python/python-feature/</url>
      
        <content type="html"><![CDATA[<article class="_2rhmJa">    <h3>从三个方面看Python</h3>    <ul>        <li>            <h4>语言特点</h4>        </li>    </ul>    <blockquote>        <p>简洁 优雅 省略了各种大括号和分号,还有一些关键字,类型说明</p>    </blockquote>    <ul>        <li>            <h4>语言类型</h4>        </li>    </ul>    <blockquote>        <p>解释型语言,运行的时候是一行一行的解释,并运行,所以调试代码很方便,开发效率高.</p>    </blockquote>    <ul>        <li>            <h4>第三方库</h4>        </li>    </ul>    <blockquote>        <p>python是开源的,并且python的定位时任由其发展,应用领域很多<br>            比如Web,运维,自动化测试,爬虫,数据分析,人工智能.Python具有非常完备的<br>            第三方库</p>    </blockquote>    <ul>        <li>            <h4>一句话概括Python语言</h4>        </li>    </ul>    <p><em>Python是一门语法简洁优美,功能强大无比,应用领域非常广泛,具有强大完备的第三方库的一门<br>        弱类型的可移植,可扩展,可嵌入的解释型编程语言</em></p>    <ul>        <li>            <h3>缺点就是</h3>        </li>        <li><strong>1. Python的执行速度不够快</strong></li>    </ul>    <blockquote>        <p>Python是一门解释型语言,所以它的速度相较于c/c++ 会慢一些.但是并不影响使用<br>            因为现在的硬件配置都非常的高,基本没什么影响.除非是一些实时性比较强的程序可能会受到<br>            一些影响,但是也是有解决办法的,可以嵌入c\c++代码</p>    </blockquote>    <ul>        <li><strong>2.Python的GIL(Global Interpreter Lock)全局解释器锁</strong></li>    </ul>    <h4>GIL是什么</h4>    <p>        首先明确一点GIL并不是Python的特性,而是解释器的特性.它是Python的解释器Cpython用来做多线程的控制和调度用的全局锁.保证同一个时刻只有一个线程在运行.Python还有一些别的解释器,比如Jpython就没有GIL锁.Cpython现在已经成了python的实现标准,所以我们都说python具有GIL限制.</p>    <p><em>GIL的问题总体上来说是历史遗留的问题,以前的计算机的程序运行方式是单核多任务的模式,所以为了防止多个任务对同一资源进行同时的操作,竞争资源,才有了全局的解释器锁.但是随着近年来科技的进步,出现了多核,这样的话,全局锁就会限制多线程的并行.</em>    </p>    <h4>解决方法</h4>    <ul>        <li>使用multiprocessing(多进程)替代Thread(多线程)<br>            multiprocessing库的的出现弥补了Python多线程并发限制的不足,每个进程都有自己独立的GIL,因此也不会出现进程之间的GIL的争夺.        </li>        <li>GIL只是Cpython解释器的产物,当然可以用其他的解释器来替代,但是由于其他的解释器,对C支持的不是很好,多以一直也不是很受欢迎.</li>        <li>Python社区也在对GIL对于多线程的支持的一些改进.比如增加线程的优先级(高优先级的线程可以迫使其他线程释放所有的GIl锁)</li>        <li>如果对并行计算性能较高的程序可以考虑把核心部分写成C模块,或者直接用其他语言代替.</li>    </ul>    <p>Python和Java相比:</p>    <blockquote>        <p>Python比Java要简单.Python是函数为一等公民的语言,而Java是类为一等公民的语言.Python是弱类型语言,而Java是强类型语言.</p>    </blockquote>    <p>Python和C相比</p>    <blockquote>        <p>对于使用:<br>            Python的类库齐全并且使用简洁,很少代码实现的功能用C可能要很复杂<br>            对于速度:<br>            Python的运行速度相较于C,绝对是很慢了.Python和CPython解释器都是C语言编写的</p>    </blockquote>    <ul>        <li>            <h4>编译性 和 解释型语言</h4>        </li>    </ul>    <blockquote>        <p>解释型:就是边解释边执行<br>            编译性:编译后再执行</p>    </blockquote></article>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python中的接口</title>
      <link href="cp/python/python-interface/"/>
      <url>cp/python/python-interface/</url>
      
        <content type="html"><![CDATA[<h3 id="什么是接口-？"><a href="#什么是接口-？" class="headerlink" title="什么是接口 ？"></a>什么是接口 ？</h3><p>接口只是定义了一些方法，而没有去实现，多用于程序设计时，只是设计需要有什么样的功能，但是并没有实现任何功能，这些功能需要被另一个类（B）继承后，由 类B去实现其中的某个功能或全部功能。</p><p>在python中接口由抽象类和抽象方法去实现，接口是不能被实例化的，只能被别的类继承去实现相应的功能。</p><p>个人觉得接口在python中并没有那么重要，因为如果要继承接口，需要把其中的每个方法全部实现，否则会报编译错误，还不如直接定义一个class，其中的方法实现全部为pass，让子类重写这些函数。</p><p>当然如果有强制要求，必须所有的实现类都必须按照接口中的定义写的话，就必须要用接口。</p><h3 id="方法一：用抽象类和抽象函数实现方法"><a href="#方法一：用抽象类和抽象函数实现方法" class="headerlink" title="方法一：用抽象类和抽象函数实现方法"></a>方法一：用抽象类和抽象函数实现方法</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">#抽象类加抽象方法就等于面向对象编程中的接口</span></span><br><span class="line"><span class="keyword">from</span> abc <span class="keyword">import</span> ABCMeta,abstractmethod</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">interface</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    __metaclass__ = ABCMeta <span class="comment">#指定这是一个抽象类</span></span><br><span class="line"><span class="meta">    @abstractmethod  </span><span class="comment">#抽象方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Lee</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Marlon</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RelalizeInterfaceLee</span>(<span class="params">interface</span>):</span><span class="comment">#必须实现interface中的所有函数，否则会编译错误</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span>    </span><br><span class="line">        <span class="built_in">print</span> <span class="string">&#x27;这是接口interface的实现&#x27;</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Lee</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">print</span> <span class="string">&#x27;实现Lee功能&#x27;</span>        </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Marlon</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">pass</span>   </span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RelalizeInterfaceMarlon</span>(<span class="params">interface</span>):</span> <span class="comment">#必须实现interface中的所有函数，否则会编译错误</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span>    </span><br><span class="line">        <span class="built_in">print</span> <span class="string">&#x27;这是接口interface的实现&#x27;</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Lee</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">pass</span>      </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Marlon</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;实现Marlon功能&quot;</span></span><br></pre></td></tr></table></figure><h3 id="方法二：用普通类定义接口"><a href="#方法二：用普通类定义接口" class="headerlink" title="方法二：用普通类定义接口"></a>方法二：用普通类定义接口</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">interface</span>(<span class="params"><span class="built_in">object</span></span>):</span> <span class="comment">#假设这就是一个接口，接口名可以随意定义，所有的子类不需要实现在这个类中的函数</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Lee</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Marlon</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Realaize_interface</span>(<span class="params">interface</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Lee</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;实现接口中的Lee函数&quot;</span></span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Realaize_interface2</span>(<span class="params">interface</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">Marlon</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;实现接口中的Marlon函数&quot;</span></span><br><span class="line">     </span><br><span class="line">obj=Realaize_interface()</span><br><span class="line">obj.Lee()</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">obj=Realaize_interface2()</span><br><span class="line">obj.Marlon()</span><br></pre></td></tr></table></figure><p>原文链接:<a href="https://blog.csdn.net/kobeyan/article/details/44344087">https://blog.csdn.net/kobeyan/article/details/44344087</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python 的解释器种类以及相关特点</title>
      <link href="cp/python/python-interpreter-type/"/>
      <url>cp/python/python-interpreter-type/</url>
      
        <content type="html"><![CDATA[<h3 id="CPython"><a href="#CPython" class="headerlink" title="CPython"></a>CPython</h3><p>当从Python官方网站下载并安装好Python2.7后，就直接获得了一个官方版本的解释器：Cpython，这个解释器是用C语言开发的，所以叫CPython，在命名行下运行python，就是启动CPython解释器，CPython是使用最广的Python解释器。</p><h3 id="IPython"><a href="#IPython" class="headerlink" title="IPython"></a>IPython</h3><p>IPython是基于CPython之上的一个交互式解释器，也就是说，IPython只是在交互方式上有所增强，但是执行Python代码的功能和CPython是完全一样的，好比很多国产浏览器虽然外观不同，但内核其实是调用了IE。</p><h3 id="PyPy"><a href="#PyPy" class="headerlink" title="PyPy"></a>PyPy</h3><p>PyPy是另一个Python解释器，它的目标是执行速度，PyPy采用JIT技术，对Python代码进行动态编译，所以可以显著提高Python代码的执行速度。</p><h3 id="Jython"><a href="#Jython" class="headerlink" title="Jython"></a>Jython</h3><p>Jython是运行在Java平台上的Python解释器，可以直接把Python代码编译成Java字节码执行。</p><h3 id="IronPython"><a href="#IronPython" class="headerlink" title="IronPython"></a>IronPython</h3><p>IronPython和Jython类似，只不过IronPython是运行在微软.Net平台上的Python解释器，可以直接把Python代码编译成.Net的字节码。</p>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>深入python内存管理</title>
      <link href="cp/python/python-memory-management/"/>
      <url>cp/python/python-memory-management/</url>
      
        <content type="html"><![CDATA[<h3 id="本文目录"><a href="#本文目录" class="headerlink" title="本文目录"></a>本文目录</h3><ol><li>对象的内存使用</li><li>对象引用对象</li><li>引用减少</li><li>垃圾回收</li><li>分代回收</li><li>孤立的引用环</li><li>总结</li></ol><div class="post-body" itemprop="articleBody" style="opacity: 1; display: block; transform: translateY(0px);"><p>    面试中被问到python的内存管理，只是说是python有自己的内存管理机制，有自己的垃圾回收机制，却不能详细作答，面试官表示很遗憾。建议我代码的业务逻辑需要想，但是学习需要深入底层，也有助于扩宽自己的知识面，对自己之后的学习路径有帮助，哈哈，感谢面试官帮我指出自己的不足。</p><p>回家马上查资料，先解决这个问题。</p><p>首先看看各种python常见面试题上的答案：</p><blockquote>    <p>        python内存管理是由私有堆空间管理的，所有的python对象和数据结构都存储在私有堆空间中。程序员没有访问堆的权限，只有解释器才能操作。为python的堆空间分配内存的是python的内存管理模块进行的，核心api会提供一些访问该模块的方法供程序员使用。python自有的垃圾回收机制回收并释放没有被使用的内存供别的程序使用。</p></blockquote><p>如果仅仅问道这，上面的答案也足够了，但是面试官想要了解到更多，可能会衍生一些别的问题，那上面的答案就不够了。</p><a id="more"></a><p>以下内容： 作者：Vamei 出处：<a href="http://www.cnblogs.com/vamei" target="_blank" rel="noopener">http://www.cnblogs.com/vamei</a>    欢迎转载，也请保留这段声明。谢谢！</p><p>语言的内存管理是语言设计的一个重要方面。他是决定语言性能的重要因素。无论是C的手动管理还是java的垃圾回收，都成为语言重要的特征。下面已python语言为例子，说明一门动态类型的面向对象的语言的内存管理方式。</p><hr><h3 id="对象的内存使用"><a href="#对象的内存使用" class="headerlink" title="对象的内存使用"></a>对象的内存使用</h3><p>赋值语句是语言最常见的功能了。但即使是最简单的赋值语句，也可以很有内涵. 首先看看python的赋值语句：</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line">a = <span class="number">1</span></span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>    整数“1”为一个对象，存储在内存空间中。a是一个引用。利用赋值语句，将引用a指向对象1。Python是动态类型的语言，对象与引用分离。文章作者比较形象的解释就是：Python像使用“筷子”那样，通过引用来接触和翻动真正的食物——对象。</p><p><strong>下面就是一系列的实验了，建议亲自尝试</strong> 可以通过python的内置函数id()，来探索对象在内存的存储。</p><div class="highlight-wrap">    <figure class="highlight shell">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="meta">&gt;</span><span                                class="bash">&gt;&gt; a = 1</span></span><br><span class="line"><span class="meta">&gt;</span><span                                class="bash">&gt;&gt; id(a)</span></span><br><span class="line">140035503539424  # 内存地址的十进制表示</span><br><span                                class="line"><span class="meta">&gt;</span><span                                class="bash">&gt;&gt; hex(id(a))</span></span><br><span class="line">'0x7f5c8e71c4e0'  # 内存地址的十六进制表示</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>在python中整数和短小的字符，python都会缓存这些对象，以便重复使用，当我们创建多个等于1的引用的时候，实际是让所有引用都指向同一个对象：</p><div class="highlight-wrap">    <figure class="highlight shell">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="meta">&gt;</span><span                                class="bash">&gt;&gt; b = 1</span></span><br><span class="line"><span class="meta">&gt;</span><span                                class="bash">&gt;&gt; id(b)</span></span><br><span class="line">140035503539424  # 等于上面id(a)的值</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>对比可以看出a和b实际是指向同一个对象的不同引用。 为了校验两个引用指向同一个对象，我们可以用“is”来判断。is用于判断两个引用所指的对象是否相同。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br><span class="line">6</span><br><span                                class="line">7</span><br><span class="line">8</span><br><span                                class="line">9</span><br><span class="line">10</span><br><span                                class="line">11</span><br><span class="line">12</span><br><span                                class="line">13</span><br><span class="line">14</span><br><span                                class="line">15</span><br><span class="line">16</span><br><span                                class="line">17</span><br><span class="line">18</span><br><span                                class="line">19</span><br><span class="line">20</span><br><span                                class="line">21</span><br><span class="line">22</span><br><span                                class="line">23</span><br><span class="line">24</span><br><span                                class="line">25</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line">a = <span class="number">1</span></span><br><span                                class="line">b = <span class="number">1</span></span><br><span class="line">print(a <span                                class="keyword">is</span> b)</span><br><span class="line"><span                                class="literal">True</span></span><br><span class="line"></span><br><span                                class="line">a = <span class="string">"good"</span></span><br><span class="line">b = <span                                class="string">"good"</span></span><br><span class="line">print(a <span                                class="keyword">is</span> b)</span><br><span class="line"><span                                class="literal">True</span></span><br><span class="line"></span><br><span                                class="line">a = <span class="string">"very good morning"</span></span><br><span                                class="line">b = <span class="string">"very good morning"</span></span><br><span                                class="line">print(a <span class="keyword">is</span> b)</span><br><span                                class="line"><span class="literal">True</span>   <span class="comment"># 原文在此处就是False，但是我的为True，通过查资料发现是python版本原因</span></span><br><span                                class="line"><span class="comment"># Python2.3简单整数缓存范围是(-1,100)，Python2.5.4以后简单整数缓存范围至少是(-5,256)。所有的短字符也都在缓存区。</span></span><br><span                                class="line"></span><br><span class="line">a = <span class="string">"为了校验两个引用指向同一个对象，我们可以用“is”来判断。is用于判断两个引用所指的对象是否相同。"</span></span><br><span                                class="line">b = <span class="string">"为了校验两个引用指向同一个对象，我们可以用“is”来判断。is用于判断两个引用所指的对象是否相同。"</span></span><br><span                                class="line">print(a <span class="keyword">is</span> b)</span><br><span                                class="line"><span class="literal">False</span>  <span class="comment"># 增加了字符串的长度，结果也是False</span></span><br><span                                class="line"></span><br><span class="line">a = []</span><br><span class="line">b = []</span><br><span                                class="line">print(a <span class="keyword">is</span> b)</span><br><span                                class="line"><span class="literal">False</span></span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>    根据上面的运行结果，可以看到由于python缓存了整数和短字符串，因此每个对象只存有一份。比如所有的1的引用都指向同一对象。即使使用赋值语句，也只是创造了新的引用，而不是对象本身，长的字符串和其他对象可以有多个相同对象，可以使用赋值语句创建出新的对象。</p><p>在python中，每个对象都有存有指向该对象的应用总数，即<strong><em>引用计数(reference count)</em></strong> 呢 我们可以使用<code>sys</code>包中的<code>getrefcount()</code>，来查看某个对象的引用计数。需要注意的是，当使用某个引用作为参数，传递给<code>getrefcount()</code>时，会创建一个临时引用，所以结果会比预期多1。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br><span class="line">6</span><br><span                                class="line">7</span><br><span class="line">8</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="keyword">from</span> sys <span                                class="keyword">import</span> getrefcount</span><br><span                                class="line"></span><br><span class="line">a = [<span class="number">1</span>, <span                                class="number">2</span>, <span class="number">3</span>]</span><br><span                                class="line">print(getrefcount(a))</span><br><span class="line"><span                                class="comment"># 2</span></span><br><span class="line">b = a</span><br><span                                class="line">print(getrefcount(b))</span><br><span class="line"><span                                class="comment"># 3</span></span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>由于上述原因，<code>getrefcount()</code>返回的结果分别是2,3，而不是期望的1。</p><hr><h3 id="对象引用对象"><a href="#对象引用对象" class="headerlink" title="对象引用对象"></a>对象引用对象</h3><p>python的一个容器对象（container），比如列表字典等，可以包含多个对象。实际上，容器对象中包含的并不是对象本身，而是指向各个元素对象的引用。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br><span class="line">6</span><br><span                                class="line">7</span><br><span class="line">8</span><br><span                                class="line">9</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="class"><span class="keyword">class</span> <span                                class="title">from_obj</span><span class="params">(object)</span>:</span></span><br><span                                class="line">    <span class="function"><span class="keyword">def</span> <span                                class="title">__init__</span><span                                class="params">(self, to_obj)</span>:</span></span><br><span class="line">        self.to_obj = to_obj</span><br><span                                class="line">b = [<span class="number">1</span>,<span class="number">2</span>,<span                                class="number">3</span>]</span><br><span                                class="line">a = from_obj(b)</span><br><span class="line">print(id(a.to_obj))</span><br><span                                class="line">print(id(b))</span><br><span class="line"><span class="comment"># 140035473779144</span></span><br><span                                class="line"><span class="comment"># 140035473779144</span></span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>可以看到a引用了对象b。</p><p>对象引用对象是python最基本的构成方式。即使是a = 1这一赋值方式，实际上是让词典的一个键值“a”的元素引用整数对象1。该词典对象用于记录所有的全局引用。该词典引用了整数对象1。我们可以通过内置函数<code>globals()</code>来查看该词典。    当一个对象a被另一个对象b引用时，a的引用计数将增加1。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br><span class="line">6</span><br><span                                class="line">7</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="keyword">from</span> sys <span                                class="keyword">import</span> getrefcount</span><br><span class="line">a = [<span                                class="number">1</span>, <span class="number">2</span>, <span                                class="number">3</span>]</span><br><span                                class="line">print(getrefcount(a))</span><br><span                                class="line">b = [a, a]</span><br><span                                class="line">print(getrefcount(a))</span><br><span class="line"><span                                class="comment"># 2</span></span><br><span class="line"><span                                class="comment"># 4</span></span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>由于对象b引用了a两次，所以a的引用计数加2。</p><p>容器对象引用可能构成很复杂的拓扑结构。我们可以用objgraph包来绘制其引用关系。 objgraph是python的一个第三方包。<a href="http://mg.pov.lt/objgraph/"                                                                        target="_blank"                                                                        rel="noopener">objgraph官网</a>。</p><div class="highlight-wrap">    <figure class="highlight bash">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line">pip install objgraph</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p> 使用objgraph需要安装xdot。根据自己的系统发行版本安装。</p><div class="highlight-wrap">    <figure class="highlight bash">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br></pre>                    </td>                    <td class="code">                        <pre><span                                class="line">sudo pacman -S xdot或者 sudo apt install xdot，sudo yun install xdot</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br><span class="line">6</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line">x = [<span class="number">1</span>, <span                                class="number">2</span>, <span class="number">3</span>]</span><br><span                                class="line">y = [x, dict(key1=x)]</span><br><span                                class="line">z = [y, (x, y)]</span><br><span class="line"></span><br><span                                class="line"><span class="keyword">import</span> objgraph</span><br><span                                class="line">objgraph.show_refs([z], filename=<span                                class="string">'ref_topo.png'</span>)</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p><img src= "/img/loading.gif" data-lazy-src="https://i.loli.net/2019/08/14/Tlr7paBWn3y9jGQ.png" alt="ref_topo.png"></p><p>两个对象可能互相引用，从而构成所谓的引用环（reference cycle）</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>a = []</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span>b = [a]</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span>a.append(b)</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span>a</span><br><span class="line">[[[...]]]</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>即使是一个对象，只需要自己引用自己，也能构成引用环。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>a = []</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span>a.append(a)</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span>print(getrefcount(a))</span><br><span                                class="line"><span class="number">3</span></span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>引用环会给垃圾回收机制带来很大的麻烦，我将在后面详细叙述这一点。</p><hr><h3 id="引用减少"><a href="#引用减少" class="headerlink" title="引用减少"></a>引用减少</h3><p>某个引用对象的引用计数可能减少。比如使用del关键字删除某个引用</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br><span class="line">6</span><br><span                                class="line">7</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>a = [<span                                class="number">1</span>, <span class="number">2</span>, <span                                class="number">3</span>]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>b = a</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span>print(getrefcount(b))</span><br><span                                class="line"><span class="number">3</span></span><br><span class="line"><span                                class="meta">&gt;&gt;&gt; </span><span class="keyword">del</span> a</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span>print(getrefcount(b))</span><br><span                                class="line"><span class="number">2</span></span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>del也可以删除容器中的元素，比如：</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br><span class="line">6</span><br><span                                class="line">7</span><br><span class="line">8</span><br><span                                class="line">9</span><br><span class="line">10</span><br><span                                class="line">11</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>a = [<span                                class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">del</span> a[<span                                class="number">0</span>]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>print(a)</span><br><span                                class="line">[<span class="number">2</span>, <span                                class="number">3</span>]</span><br><span class="line"></span><br><span class="line"><span                                class="meta">&gt;&gt;&gt; </span>b = {<span class="string">"q"</span>: <span                                class="number">1</span>, <span class="string">"w"</span>:<span                                class="number">2</span>}</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>b</span><br><span                                class="line">{<span class="string">'q'</span>: <span class="number">1</span>, <span                                class="string">'w'</span>: <span class="number">2</span>}</span><br><span                                class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">del</span> b[<span                                class="string">"q"</span>]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>b</span><br><span                                class="line">{<span class="string">'w'</span>: <span class="number">2</span>}</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>如果某个引用指向对象a，当这个引用被重新定向到其他对象b的时候，对象a的引用计数会减少</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br><span class="line">6</span><br><span                                class="line">7</span><br><span class="line">8</span><br><span                                class="line">9</span><br><span class="line">10</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span                                class="keyword">from</span> sys <span                                class="keyword">import</span> getrefcount</span><br><span                                class="line">...</span><br><span class="line"><span                                class="meta">... </span>a = [<span class="number">1</span>, <span                                class="number">2</span>, <span class="number">3</span>]</span><br><span                                class="line"><span class="meta">... </span>b = a</span><br><span class="line"><span                                class="meta">... </span>print(getrefcount(b))</span><br><span                                class="line">...</span><br><span class="line"><span                                class="meta">... </span>a = <span class="number">1</span></span><br><span                                class="line"><span class="meta">... </span>print(getrefcount(b))</span><br><span                                class="line"><span class="number">3</span></span><br><span class="line"><span                                class="number">2</span></span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><hr><h3 id="垃圾回收"><a href="#垃圾回收" class="headerlink" title="垃圾回收"></a>垃圾回收</h3><p>当python中的对象越来越多，他占据的内存也会越来越大。不过不需要担心太多，python会在适当的时候启动垃圾<code>回收机制(garbage collection)</code>，将没用的对象清除，在许多语言中都有垃圾回收机制，比如Java和Ruby。</p><p>从基本原理来说，当一个对象的引用计数降为0的时候，说明没有任何引用指向对象，这时候该对象就成为需要被清除的垃圾了。比如某个新建对象，分配给某个引用，引用数为1,当引用被删除之后，引用数为0，那么该对象就可以被垃圾回收。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line">a = [<span class="number">1</span>,<span                                class="number">2</span>,<span class="number">3</span>]</span><br><span class="line"><span                                class="keyword">del</span> a</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p><code>del    a</code>之后已经没有任何引用指向[1,2,3]了，用户不可能通过任何方式接触或者动用这个对象，这个对象如果继续待在内存里，就成了不健康的数据。当python的<strong><em>垃圾回收</em></strong>机制启动的时候，python扫描到这个引用为0的对象，就会将它所占据的内存清空。</p><p>    然而清理过程是个费力的过程。垃圾回收的时候，python不能进行其他的任务，频繁的垃圾回收，会大大降低python的工作效率。如果内存中的对象不多，就没必要总启动垃圾回收。所以python只会在特定的条件下，<strong><em>自动启动垃圾回收</em></strong>。当python运行的时候，会记录其中分配对象和取消分配对象的次数，两者的差值高于某个阈值的时候，垃圾回收才会启动。    我们可以通过gc模块的<code>get_threshold()</code>来查看该阈值。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span                                class="keyword">import</span> gc</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>gc.get_threshold()</span><br><span                                class="line">(<span class="number">700</span>, <span class="number">10</span>, <span                                class="number">10</span>)</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>返回值中，后面的两个10,是与分代回收相关的阈值，分代回收在后面会讲到。700既是垃圾回收的启动阈值。可以通过gc中的<code>set_threshold()</code>来重新设定。 也可以手动使用<code>gc.collect()</code>启动垃圾回收机制。</p><hr><h3 id="分代回收"><a href="#分代回收" class="headerlink" title="分代回收"></a>分代回收</h3><p>    python同时使用了分代（generation）回收的策略。这一策略的基本假设是，存活时间越久的对象，越不可能在后面的程序中变成垃圾。我们的程序往往会产生大量的对象，许多对象很快产生和消失，但也有长期存在被使用的对象，出于信任和效率，对于这样一些对象，我们相信他的用处，所以减少在垃圾回收中扫描他们的频率。</p><p>    python将所有的对象分为0,1,2三代，所有新建的对象都是0代对象，当某一代对象经历过垃圾回收之后，依然存活，那就归入到下一代中，垃圾回收启动时，一定会扫描所有的0代对象。如果0代对象经历过一定次数的垃圾回收，那么就启动对0待和1代的扫描清理，当1代也经历了一定数量的垃圾回收，那就启动对0,1,2，即所有的对象进行扫描。</p><p>上面<code>gc.get_threshold()</code>返回的（700,10,10）中后面的两个数，意义就是，每经过10次对0代的垃圾回收，就会配合启动一次对1代的扫描，没经过10次对1代的扫描，才会启动一次对2代的垃圾回收。</p><p>同样可以用set_threshold()来调整，比如对2代对象进行更频繁的扫描。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line"><span class="keyword">import</span> gc</span><br><span class="line">gc.set_threshold(<span                                class="number">700</span>, <span class="number">10</span>, <span                                class="number">5</span>)</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><hr><h3 id="孤立的引用环"><a href="#孤立的引用环" class="headerlink" title="孤立的引用环"></a>孤立的引用环</h3><p>引用环的存在会给垃圾回收带来很大的困难，这些引用环可能构成无法使用，但是引用计数不为0的一些对象。</p><div class="highlight-wrap">    <figure class="highlight python">        <div class="table-container">            <table>                <tbody>                <tr>                    <td class="gutter">                        <pre><span class="line">1</span><br><span class="line">2</span><br><span                                class="line">3</span><br><span class="line">4</span><br><span                                class="line">5</span><br></pre>                    </td>                    <td class="code">                        <pre><span class="line">a = []</span><br><span class="line">b = [a]</span><br><span                                class="line">a.append(b)</span><br><span class="line"><span                                class="keyword">del</span> a</span><br><span class="line"><span                                class="keyword">del</span> b</span><br></pre>                    </td>                </tr>                </tbody>            </table>        </div>    </figure>    <div class="copy-btn"><i class="fa fa-clipboard"></i></div></div><p>上面我们先创建了两个表对象，并引用对方，构成一个引用环。删除了a，b引用之后，这两个对象不可能再从程序中调用，就没有什么用处了。但是由于引用环的存在，这两个对象的引用计数都没有降到0，不会被垃圾回收。 <img        src="https://i.loli.net/2019/08/14/KZiDkvBopAafMHh.png" alt="孤立的引用环"></p><p>为了回收这样的引用环，Python复制每个对象的引用计数，可以记为gc_ref。假设，每个对象i，该计数为gc_ref_i。Python会遍历所有的对象i。对于每个对象i引用的对象j，将相应的gc_ref_j减1。 <img        src="https://i.loli.net/2019/08/14/SezEXqxlitfMA1P.png" alt="遍历后的结果">    在结束遍历后，gc_ref不为0的对象，和这些对象引用的对象，以及继续更下游引用的对象，需要被保留。而其它的对象则被垃圾回收。</p><hr><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>    python作为一种动态类型的语言，其对象和引用分离，这与面向过程的编程语言有很大的区别。为了有效的释放内存，python内置了垃圾回收的支持。python采用了一种相对简单的垃圾回收机制，即引用计数，并因此需要解决孤立引用环的问题。Python与其它语言既有共通性，又有特别的地方。对该内存管理机制的理解，是提高Python性能的重要一步。</p></div><p>原文链接:<a href="https://zz.zzs7.top/python-memory-management.html">https://zz.zzs7.top/python-memory-management.html</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>啥是猴子补丁</title>
      <link href="cp/python/python-monkey/"/>
      <url>cp/python/python-monkey/</url>
      
        <content type="html"><![CDATA[<h3 id="Python猴子补丁"><a href="#Python猴子补丁" class="headerlink" title="Python猴子补丁"></a>Python猴子补丁</h3><p>推荐阅读：<a href="https://www.jianshu.com/p/f1060b22aab8">python自定义对象转json串</a></p><blockquote>    <p>属性在运行时的动态替换，叫做猴子补丁（Monkey Patch）。</p></blockquote><h1>为什么叫猴子补丁</h1><p>属性的运行时替换和猴子也没什么关系，关于猴子补丁的由来网上查到两种说法：</p><blockquote>    <p>1，这个词原来为Guerrilla Patch，杂牌军、游击队，说明这部分不是原装的，在英文里guerilla发音和gorllia(猩猩)相似，再后来就写了monkey(猴子)。<br>        2，还有一种解释是说由于这种方式将原来的代码弄乱了(messing with it)，在英文里叫monkeying about(顽皮的)，所以叫做Monkey Patch。</p></blockquote><p>猴子补丁的叫法有些莫名其妙，只要和“模块运行时替换的功能”对应就行了。</p><h1>猴子补丁的用法</h1><h2>1，运行时动态替换模块的方法</h2><p>stackoverflow上有两个比较热的例子，</p><blockquote>    <p>consider a class that has a method get_data. This method does an external lookup (on a database or web        API, for example), and various other methods in the class call it. However, in a unit test, you don't        want to depend on the external data source - so you dynamically replace the get_data method with a stub        that returns some fixed data.<br>        假设一个类有一个方法get_data。这个方法做一些外部查询（如查询数据库或者Web        API等），类里面的很多其他方法都调用了它。然而，在一个单元测试中，你不想依赖外部数据源。所以你用哑方法态替换了这个get_data方法，哑方法只返回一些测试数据。</p></blockquote><p>另一个例子引用了，Zope wiki上对Monkey Patch解释：</p><pre class="line-numbers  language-python"><code class="  language-python"><span        class="token keyword">from</span> SomeOtherProduct<span        class="token punctuation">.</span>SomeModule <span class="token keyword">import</span> SomeClass<p><span class="token keyword">def</span> <span class="token function">speak</span><span class="token punctuation">(</span>self<span            class="token punctuation">)</span><span class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token string">“ook ook eee eee eee!”</span></p><p>SomeClass<span class="token punctuation">.</span>speak <span class="token operator">=</span> speak<br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>还有一个比较实用的例子，很多代码用到 import json，后来发现ujson性能更高，如果觉得把每个文件的import json 改成 import ujson as    json成本较高，或者说想测试一下用ujson替换json是否符合预期，只需要在入口加上：</p><pre class="line-numbers  language-python"><code class="  language-python"><span        class="token keyword">import</span> json<span class="token keyword">import</span> ujson<p><span class="token keyword">def</span> <span class="token function">monkey_patch_json</span><span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span><br>    json<span class="token punctuation">.</span><strong>name</strong> <span class="token operator">=</span> <span            class="token string">‘ujson’</span><br>    json<span class="token punctuation">.</span>dumps <span class="token operator">=</span> ujson<span            class="token punctuation">.</span>dumps<br>    json<span class="token punctuation">.</span>loads <span class="token operator">=</span> ujson<span            class="token punctuation">.</span>loads</p><p>monkey_patch_json<span class="token punctuation">(</span><span class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><h2>2，运行时动态增加模块的方法</h2><p>这种场景也比较多，比如我们引用团队通用库里的一个模块，又想丰富模块的功能，除了继承之外也可以考虑用Monkey Patch。<br>    个人感觉Monkey Patch带了便利的同时也有搞乱源代码优雅的风险。</p><h1>参考：</h1><blockquote>    <p><a href="https://link.jianshu.com?t=http://stackoverflow.com/questions/5626193/what-is-a-monkey-patch"          target="_blank"          rel="nofollow">http://stackoverflow.com/questions/5626193/what-is-a-monkey-patch</a><br>        <a href="https://www.jianshu.com/p/f1060b22aab8"           target="_blank">http://www.jianshu.com/p/f1060b22aab8</a><br>        <a href="https://link.jianshu.com?t=http://blog.csdn.net/handsomekang/article/details/40297775"           target="_blank" rel="nofollow">http://blog.csdn.net/handsomekang/article/details/40297775</a></p></blockquote>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python的编码命名规则</title>
      <link href="cp/python/python-name-rule/"/>
      <url>cp/python/python-name-rule/</url>
      
        <content type="html"><![CDATA[<article class="_2rhmJa">    <ul>        <li>            <h3>项目名</h3>        </li>    </ul>    <blockquote>        <p>首字母大写，其余小写单词，若多个单词组合可以添加“_”下划线增加可读性<br>            Ui_test</p>    </blockquote>    <ul>        <li>            <h3>包名、模块名</h3>        </li>    </ul>    <blockquote>        <p>全部小写字母<br>            package、 module</p>    </blockquote>    <ul>        <li>            <h3>类名</h3>        </li>    </ul>    <blockquote>        <p>首字母大写，其它字母小写，若多个单词时，才用驼峰，eg：UserLogin<br>            class Login :</p>    </blockquote>    <ul>        <li>            <h3>方法名</h3>        </li>    </ul>    <blockquote>        <p>小写单词，多个单词时，用下划线分隔单词以增加可读性。<br>            def user_login():</p>    </blockquote>    <ul>        <li>            <h3>参数名</h3>        </li>    </ul>    <blockquote>        <p>小写单词<br>            def user_login(self):<br>            如果函数的参数名与保留关键字冲突，在参数名后加一个下划线，比用缩写、错误 的拼写要好。因此 "_print" 比 "prnt" 好。</p>    </blockquote>    <ul>        <li>            <h3>普通变量名</h3>        </li>    </ul>    <blockquote>        <p>小写字母，单词之间用<em>分割 或者 遵守驼峰原则命名<br>            month_pay = 2000<br>            monthPay = 2000<br>            <em>注意</em>：<br>            1.不论是类成员变量还是全局变量，均不使用 m 或 g 前缀。<br>            2.私有类成员使用单一下划线前缀标识，多定义公开成员，少定义私有成员。<br>            3.变量名不应带有类型信息，因为Python是动态类型语言。如 iValue、names_list、dict_obj 等都是不好的命名。<br>            4.</em><em>开头，</em><em>结尾，一般为python的自有变量，不要以这种方式命名<br>            5.以</em>_开头（2个下划线），是私有实例变量（外部不嫩直接访问），依照情况进行命名</p>    </blockquote>    <ul>        <li>            <h3>常量</h3>        </li>    </ul>    <blockquote>        <p>常量定义全部为大写，必要时可用下划线分隔单词以增加可读性。<br>            constant</p>    </blockquote>    <ul>        <li>            <h3>命名注意：</h3>        </li>    </ul>    <blockquote>        <p>不要使用小写字母'l'(el),大写字母'O'(oh),或者小写'i'作为单独变量名称。因为一些字体中，上诉字母和数字很难区分（比如：O和0，l和1）。</p>    </blockquote></article>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PEP8 Python 编码规范</title>
      <link href="cp/python/python-pep8/"/>
      <url>cp/python/python-pep8/</url>
      
        <content type="html"><![CDATA[<div id="article_content" class="article_content clearfix">    <div id="content_views" class="markdown_views"><pre><code>    &lt;h1 id=&quot;1-pep8&quot;&gt;&lt;a name=&quot;t0&quot;&gt;&lt;/a&gt;1. PEP8&lt;/h1&gt;    &lt;p&gt;&lt;strong&gt;什么是PEP&lt;/strong&gt; &lt;br&gt;        PEP是 Python Enhancement Proposal 的缩写，翻译过来就是 Python增强建议书 。 &lt;br&gt;        &lt;strong&gt;PEP8&lt;/strong&gt; &lt;br&gt;        译者：本文基于 2013-08-02 最后修改的 PEP8 版本翻译，若要查看英文原文，请参考&lt;a href=&quot;http://www.python.org/dev/peps/pep-0008/&quot;                                                          rel=&quot;nofollow&quot;&gt;PEP8&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;许多项目都有一套专有的编码风格指南，当冲突发生时，应以项目编码规范为优先。 &lt;br&gt;        当以下情况发生时，也是忽略某个风格指南的好理由：&lt;/p&gt;    &lt;ul&gt;        &lt;li&gt;当遵守指南会降低代码可读性，甚至对于那些依循 PEP 去阅读代码的人也是这样时。&lt;/li&gt;        &lt;li&gt;当遵守指南会与其他部分的代码风格背离时 — 当然也许这是一个修正某些混乱代码的机会。&lt;/li&gt;        &lt;li&gt;当那些并没有遵循指南的旧代码已无法修改时。&lt;/li&gt;        &lt;li&gt;当你的代码需要与旧版本的 Python 保持兼容，而旧版本的 Python 不支持指南中提到的特性时。&lt;/li&gt;    &lt;/ul&gt;    &lt;h1 id=&quot;2-代码布局&quot;&gt;&lt;a name=&quot;t1&quot;&gt;&lt;/a&gt;2. 代码布局&lt;/h1&gt;    &lt;h2 id=&quot;21-缩进&quot;&gt;&lt;a name=&quot;t2&quot;&gt;&lt;/a&gt;2.1 缩进&lt;/h2&gt;    &lt;p&gt;每次缩进使用 4 个空格。&lt;/p&gt;    &lt;p&gt;续行应该与被圆括号、方括号、花括号包裹起来的其他元素对齐，或者使用悬挂式缩进。当使用悬挂式缩进时，应该遵循这些注意事项：第一行不能有参数，应该使用进一步的缩进来将续行与其他行区分开。&lt;/p&gt;    &lt;p&gt;符合本约定的代码：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Aligned with opening delimiter&lt;/span&gt;</code></pre><p>foo = long_function_name(var_one, var_two,<br>                 var_three, var_four)</p><p><span class="hljs-comment"># More indentation included to distinguish this from the rest.</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span        class="hljs-title">long_function_name</span><span class="hljs-params">(<br>var_one, var_two, var_three,<br>var_four)</span>:</span><br>print(var_one)<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li                style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li                style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li                style="color: rgb(153, 153, 153);">9</li></ul></pre></p><pre><code>    &lt;p&gt;不符合本约定的代码：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Arguments on first line forbidden when not using vertical alignment&lt;/span&gt;</code></pre><p>foo = long_function_name(var_one, var_two,<br>var_three, var_four)</p><p><span class="hljs-comment"># Further indentation required as indentation is not distinguishable</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span        class="hljs-title">long_function_name</span><span class="hljs-params">(<br>var_one, var_two, var_three,<br>var_four)</span>:</span><br>print(var_one)<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li                style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li                style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li                style="color: rgb(153, 153, 153);">9</li></ul></pre></p><pre><code>    &lt;p&gt;可选的符合约定的代码：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs vala has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-preprocessor&quot;&gt;# Extra indentation is not necessary.&lt;/span&gt;</code></pre><p>foo = long_function_name(<br>var_one, var_two,<br>var_three, var_four)<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre></p><pre><code>    &lt;p&gt;结尾的括号另起一行，如下所示：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs livecodeserver has-numbering&quot;                                               onclick=&quot;mdcp.copyCode(event)&quot; style=&quot;position: unset;&quot;&gt;my_list = [</code></pre><p><span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>,<br><span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>,<br>]<br><span class="hljs-built_in">result</span> = some_function_that_takes_arguments(<br><span class="hljs-string">‘a’</span>, <span class="hljs-string">‘b’</span>, <span class="hljs-string">‘c’</span>,<br><span class="hljs-string">‘d’</span>, <span class="hljs-string">‘e’</span>, <span class="hljs-string">‘f’</span>,<br>)<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li                style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li                style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre></p><pre><code>    &lt;p&gt;or&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs livecodeserver has-numbering&quot;                                               onclick=&quot;mdcp.copyCode(event)&quot; style=&quot;position: unset;&quot;&gt;my_list = [</code></pre><p><span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>,<br><span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>,<br>]<br><span class="hljs-built_in">result</span> = some_function_that_takes_arguments(<br><span class="hljs-string">‘a’</span>, <span class="hljs-string">‘b’</span>, <span class="hljs-string">‘c’</span>,<br><span class="hljs-string">‘d’</span>, <span class="hljs-string">‘e’</span>, <span class="hljs-string">‘f’</span>,<br>)<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li                style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li                style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre></p><pre><code>    &lt;h2 id=&quot;22-制表符&quot;&gt;&lt;a name=&quot;t3&quot;&gt;&lt;/a&gt;2.2 制表符&lt;/h2&gt;    &lt;p&gt;不使用Tap，更不能混合使用Tap和空格&lt;/p&gt;    &lt;blockquote&gt;        &lt;p&gt;Python 3 不支持空格缩进与制表符缩进混用。 &lt;br&gt;            Python 2 中的混用缩进代码也应该被转换为统一使用空格。 &lt;br&gt;            当使用 -t 选项来调用 Python 2 命令行工具时，运行混用缩进的代码会报出警告，当使用 -tt 选项时，运行混用缩进的代码会报出错误。强力建议使用这两个选项。&lt;/p&gt;    &lt;/blockquote&gt;    &lt;h2 id=&quot;23-单行最大长度&quot;&gt;&lt;a name=&quot;t4&quot;&gt;&lt;/a&gt;2.3 单行最大长度&lt;/h2&gt;    &lt;p&gt;每行最大长度79，换行可以使用反斜杠，最好使用圆括号。 &lt;br&gt;        文档字符串、注释等最大行宽72 &lt;br&gt;        换行点要在操作符的后边敲回车。 &lt;br&gt;        确保使用适当的行续缩进。在二元操作符两端，换行的推荐位置是在操作符之后，而不是操作符之前。&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span            class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Rectangle&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(Blob)&lt;/span&gt;:&lt;/span&gt;</code></pre><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title"><strong>init</strong></span><span        class="hljs-params">(self, width, height,<br>         color=<span class="hljs-string">‘black’</span>, emphasis=None, highlight=<span            class="hljs-number">0</span>)</span>:</span><br><span class="hljs-keyword">if</span> (width == <span class="hljs-number">0</span> <span                    class="hljs-keyword">and</span> height == <span class="hljs-number">0</span> <span                    class="hljs-keyword">and</span><br>        color == <span class="hljs-string">‘red’</span> <span class="hljs-keyword">and</span> emphasis == <span                    class="hljs-string">‘strong’</span> <span class="hljs-keyword">or</span><br>        highlight &gt; <span class="hljs-number">100</span>):<br>    <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">“sorry, you lose”</span>)<br><span class="hljs-keyword">if</span> width == <span class="hljs-number">0</span> <span                    class="hljs-keyword">and</span> height == <span class="hljs-number">0</span> <span                    class="hljs-keyword">and</span> (color == <span class="hljs-string">‘red’</span> <span                    class="hljs-keyword">or</span><br>                                   emphasis <span class="hljs-keyword">is</span> <span                    class="hljs-keyword">None</span>):<br>    <span class="hljs-keyword">raise</span> ValueError(<span                    class="hljs-string">“I don’t think so – values are %s, %s”</span> %<br>                     (width, height))<br>Blob.<strong>init</strong>(self, width, height,<br>              color, emphasis, highlight)<div class="hljs-button {2}" data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li                style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li                style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li                style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li                style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li                style="color: rgb(153, 153, 153);">14</li></ul></pre></p><pre><code>    &lt;h2 id=&quot;24-空白行&quot;&gt;&lt;a name=&quot;t5&quot;&gt;&lt;/a&gt;2.4 空白行&lt;/h2&gt;    &lt;p&gt;使用两个空白行来分隔顶级函数定义、类定义。 &lt;br&gt;        使用单个空白行来分隔类内的方法定义。 &lt;br&gt;        额外的空白行可以被（尽量少的）用来分隔几组相关的函数。在一堆相关的单行代码之间，空白行应该被省略。 &lt;br&gt;        在函数中（尽量少的）使用空白行来区分逻辑代码块。&lt;/p&gt;    &lt;h2 id=&quot;25-文档编排&quot;&gt;&lt;a name=&quot;t6&quot;&gt;&lt;/a&gt;2.5 文档编排&lt;/h2&gt;    &lt;p&gt;&lt;strong&gt;（1）模块内容的顺序&lt;/strong&gt; &lt;br&gt;        模块说明和docstring—import—globals&amp;amp;constants—其他定义。其中import部分，又按标准、三方和自己编写顺序依次排放，之间空一行。 &lt;br&gt;        &lt;strong&gt;（2）不要在一句import中多个库，比如import os, sys不推荐。&lt;/strong&gt;&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span            class=&quot;hljs-comment&quot;&gt;#符合约定的代码：     &lt;/span&gt;</code></pre><p><span class="hljs-keyword">import</span> os<br><span class="hljs-keyword">import</span> sys</p><p><span class="hljs-keyword">from</span> subprocess <span class="hljs-keyword">import</span> Popen, PIPE</p><p><span class="hljs-comment">#不符合本约定的代码：  </span><br><span class="hljs-keyword">import</span> os,sys<div class="hljs-button {2}" data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li                style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li                style="color: rgb(153, 153, 153);">8</li></ul></pre></p><pre><code>    &lt;p&gt;&lt;strong&gt;（3）如果采用from XX import XX引用库，可以省略‘module.’，都是可能出现命名冲突，这时就要采用import XX。&lt;/strong&gt; &lt;br&gt;        &lt;strong&gt;（4）多条 Import 语句总应该遵循这样的顺序书写：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;        &lt;li&gt;标准库的导入&lt;/li&gt;        &lt;li&gt;相关第三方库导入&lt;/li&gt;        &lt;li&gt;本地应用/库的相关导入&lt;/li&gt;    &lt;/ul&gt;    &lt;p&gt;&lt;strong&gt;（5）当在某个包含类的模块中导入类时，这样的书写方式是合理的：&lt;/strong&gt;&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;from&lt;/span&gt; myclass &lt;span            class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; MyClass</code></pre><p><span class="hljs-keyword">from</span> foo.bar.yourclass <span class="hljs-keyword">import</span> YourClass<div                    class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre></p><pre><code>    &lt;p&gt;但如果这样的书写方式引起类名冲突，则请这样书写：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs java has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; myclass</code></pre><p><span class="hljs-keyword">import</span> foo.bar.yourclass<div class="hljs-button {2}" data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li></ul></pre></p><pre><code>    &lt;p&gt;并使用 “myclass.MyClass” 和 “foo.bar.yourclass.YourClass” 来对其进行引用。&lt;/p&gt;    &lt;h1 id=&quot;3-空格的使用&quot;&gt;&lt;a name=&quot;t7&quot;&gt;&lt;/a&gt;3. 空格的使用&lt;/h1&gt;    &lt;p&gt;总体原则，避免不必要的空格。 &lt;br&gt;        （1）各种右括号前不要加空格。&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs css has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;#符合约定的代码</code></pre><p><span class="hljs-tag">spam</span>(<span class="hljs-tag">ham</span><span class="hljs-attr_selector">[1]</span>, <span                    class="hljs-rules">{<span class="hljs-rule"><span class="hljs-attribute">eggs</span>:<span                    class="hljs-value"> <span class="hljs-number">2</span></span></span></span>})<br>#不符合约定的代码<br><span class="hljs-tag">spam</span>( <span class="hljs-tag">ham</span><span                    class="hljs-attr_selector">[ 1 ]</span>, <span class="hljs-rules">{ <span class="hljs-rule"><span                    class="hljs-attribute">eggs</span>:<span class="hljs-value"> <span                    class="hljs-number">2</span> </span></span></span>} )<div class="hljs-button {2}"                                                                              data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li></ul></pre></p><pre><code>    &lt;p&gt;（2）逗号、冒号、分号前不要加空格。&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs php has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;#符合约定的代码&lt;/span&gt;</code></pre><p><span class="hljs-keyword">if</span> x == <span class="hljs-number">4</span>: <span class="hljs-keyword">print</span> x, y; x, y = y, x<br><span class="hljs-comment">#不符合约定的代码</span><br><span class="hljs-keyword">if</span> x == <span class="hljs-number">4</span> : <span class="hljs-keyword">print</span> x , y ; x , y = y , x<div                    class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre></p><pre><code>    &lt;p&gt;（3）函数的左括号前不要加空格。如Func(1)。&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs vala has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span            class=&quot;hljs-preprocessor&quot;&gt;#符合约定代码&lt;/span&gt;</code></pre><p>spam(<span class="hljs-number">1</span>)<br><span class="hljs-preprocessor">#不符合约定的代码</span><br>spam (<span class="hljs-number">1</span>)<div class="hljs-button {2}" data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li></ul></pre></p><pre><code>    &lt;p&gt;（4）序列的左括号前不要加空格。如list[2]。&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs php has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;#符合约定的代码&lt;/span&gt;</code></pre><p>dict[<span class="hljs-string">‘key’</span>] = <span class="hljs-keyword">list</span>[index]<br><span class="hljs-comment">#不符合约定的代码</span><br>dict [<span class="hljs-string">‘key’</span>] = <span class="hljs-keyword">list</span> [index]<div                    class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre></p><pre><code>    &lt;p&gt;（5） 操作符左右各加一个空格，不要为了对齐增加空格。&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs makefile has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;#符合约定的代码&lt;/span&gt;</code></pre><p><span class="hljs-constant">x</span> = 1<br><span class="hljs-constant">y</span> = 2<br><span class="hljs-constant">long_variable</span> = 3<br><span class="hljs-comment">#不符合约定的代码</span><br><span class="hljs-constant">x</span>             = 1<br><span class="hljs-constant">y</span>             = 2<br><span class="hljs-constant">long_variable</span> = 3<div class="hljs-button {2}" data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li                style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li                style="color: rgb(153, 153, 153);">8</li></ul></pre></p><pre><code>    &lt;p&gt;（6） 函数默认参数使用的赋值符左右省略空格。&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;#符合约定的代码&lt;/span&gt;</code></pre><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">complex</span><span        class="hljs-params">(real, imag=<span class="hljs-number">0.0</span>)</span>:</span><br><span class="hljs-keyword">return</span> magic(r=real, i=imag)<br><span class="hljs-comment">#不符合约定的代码</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">complex</span><span        class="hljs-params">(real, imag = <span class="hljs-number">0.0</span>)</span>:</span><br><span class="hljs-keyword">return</span> magic(r = real, i = imag)<div class="hljs-button {2}"                                                                       data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li                style="color: rgb(153, 153, 153);">6</li></ul></pre></p><pre><code>    &lt;p&gt;（7） 不要将多句语句写在同一行，尽管使用‘；’允许。 &lt;br&gt;        （8） if/for/while语句中，即使执行语句只有一句，也必须另起一行。&lt;/p&gt;    &lt;h1 id=&quot;4-注释&quot;&gt;&lt;a name=&quot;t8&quot;&gt;&lt;/a&gt;4. 注释&lt;/h1&gt;    &lt;p&gt;&lt;strong&gt;总体原则，错误的注释不如没有注释。所以当一段代码发生变化时，第一件事就是要修改注释！&lt;/strong&gt; &lt;br&gt;        注释必须使用英文，最好是完整的句子，首字母大写，句后要有结束符，结束符后跟两个空格，开始下一句。如果是短语，可以省略结束符。 &lt;br&gt;        &lt;strong&gt;（1）块注释&lt;/strong&gt; &lt;br&gt;        在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔。比如：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs vala has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-preprocessor&quot;&gt;# Description : Module config.&lt;/span&gt;</code></pre><p><span class="hljs-preprocessor"># </span><br><span class="hljs-preprocessor"># Input : None</span><br><span class="hljs-preprocessor">#</span><br><span class="hljs-preprocessor"># Output : None</span><div class="hljs-button {2}" data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre></p><pre><code>    &lt;p&gt;&lt;strong&gt;（2）行注释&lt;/strong&gt; &lt;br&gt;        在一句代码后加注释。比如：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs bash has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;x = x + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;           &lt;span            class=&quot;hljs-comment&quot;&gt;# Increment x&lt;/span&gt;&lt;div class=&quot;hljs-button &#123;2&#125;&quot; data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul            class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;    &lt;p&gt;但是这种方式尽量少使用。 &lt;br&gt;        &lt;strong&gt;（3）避免无谓的注释。&lt;/strong&gt;&lt;/p&gt;    &lt;h1 id=&quot;5-文档描述&quot;&gt;&lt;a name=&quot;t9&quot;&gt;&lt;/a&gt;5. 文档描述&lt;/h1&gt;    &lt;p&gt;（1）为所有的共有模块、函数、类、方法写docstrings；非共有的没有必要，但是可以写注释（在def的下一行）。 &lt;br&gt;        （2）如果docstring要换行，参考如下例子,详见&lt;a href=&quot;http://www.python.org/dev/peps/pep-0257/&quot; rel=&quot;nofollow&quot;&gt;PEP 257&lt;/a&gt;&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&quot;Return a foobang</code></pre><p>Optional plotz says to frobnicate the bizbaz first.</p><p>“””</span><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li                style="color: rgb(153, 153, 153);">5</li></ul></pre></p><pre><code>    &lt;h1 id=&quot;6-命名规范&quot;&gt;&lt;a name=&quot;t10&quot;&gt;&lt;/a&gt;6. 命名规范&lt;/h1&gt;    &lt;p&gt;&lt;strong&gt;总体原则，新编代码必须按下面命名风格进行，现有库的编码尽量保持风格。&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;        &lt;p&gt;1 尽量单独使用小写字母‘l’，大写字母‘O’等容易混淆的字母。 &lt;br&gt;            2 模块命名尽量短小，使用全部小写的方式，可以使用下划线。 &lt;br&gt;            3 包命名尽量短小，使用全部小写的方式，不可以使用下划线。 &lt;br&gt;            4 类的命名使用CapWords的方式，模块内部使用的类采用_CapWords的方式。 &lt;br&gt;            5 异常命名使用CapWords+Error后缀的方式。 &lt;br&gt;            6 全局变量尽量只在模块内有效，类似C语言中的static。实现方法有两种，一是&lt;strong&gt;all&lt;/strong&gt;机制;二是前缀一个下划线。 &lt;br&gt;            7 函数命名使用全部小写的方式，可以使用下划线。 &lt;br&gt;            8 常量命名使用全部大写的方式，可以使用下划线。 &lt;br&gt;            9 类的属性（方法和变量）命名使用全部小写的方式，可以使用下划线。 &lt;br&gt;            9 类的属性有3种作用域public、non-public和subclass API，可以理解成C++中的public、private、protected，non-public属性前，前缀一条下划线。            &lt;br&gt;            11 类的属性若与关键字名字冲突，后缀一下划线，尽量不要使用缩略等其他方式。 &lt;br&gt;            12 为避免与子类属性命名冲突，在类的一些属性前，前缀两条下划线。比如：类Foo中声明__a,访问时，只能通过Foo._Foo__a，避免歧义。如果子类也叫Foo，那就无能为力了。 &lt;br&gt;            13 类的方法第一个参数必须是self，而静态方法第一个参数必须是cls。&lt;/p&gt;    &lt;/blockquote&gt;    &lt;p&gt;&lt;strong&gt;（1）变量&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;常量 : 大写加下划线&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs  has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;USER_CONSTANT&lt;div class=&quot;hljs-button &#123;2&#125;&quot;                                                                                          data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul            class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;    &lt;p&gt;对于不会发生改变的全局变量，使用大写加下划线。&lt;/p&gt;    &lt;p&gt;私有变量 : 小写和一个前导下划线&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs  has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;_private_value&lt;div class=&quot;hljs-button &#123;2&#125;&quot;                                                                                           data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul            class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;    &lt;p&gt;Python 中不存在私有变量一说，若是遇到需要保护的变量，使用小写和一个前导下划线。但这只是程序员之间的一个约定，用于警告说明这是一个私有变量，外部类不要去访问它。但实际上，外部类还是可以访问到这个变量。&lt;/p&gt;    &lt;p&gt;内置变量 : 小写，两个前导下划线和两个后置下划线&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs markdown has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-strong&quot;&gt;__class__&lt;/span&gt;&lt;div            class=&quot;hljs-button &#123;2&#125;&quot; data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li            style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;    &lt;p&gt;两个前导下划线会导致变量在解释期间被更名。这是为了避免内置变量和其他变量产生冲突。用户定义的变量要严格避免这种风格。以免导致混乱。&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;（2）函数和方法&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;总体而言应该使用，小写和下划线。但有些比较老的库使用的是混合大小写，即首单词小写，之后每个单词第一个字母大写，其余小写。但现在，小写和下划线已成为规范。&lt;/p&gt;    &lt;p&gt;私有方法 ： 小写和一个前导下划线&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span            class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;_secrete&lt;/span&gt;&lt;span            class=&quot;hljs-params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;</code></pre><p><span class="hljs-keyword">print</span> <span class="hljs-string">“don’t test me.”</span><div                    class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre></p><pre><code>    &lt;p&gt;这里和私有变量一样，并不是真正的私有访问权限。同时也应该注意一般函数不要使用两个前导下划线(当遇到两个前导下划线时，Python 的名称改编特性将发挥作用)。特殊函数后面会提及。&lt;/p&gt;    &lt;p&gt;特殊方法 ： 小写和两个前导下划线，两个后置下划线&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span            class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__add__&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(self, other)&lt;/span&gt;:&lt;/span&gt;</code></pre><p><span class="hljs-keyword">return</span> int.<strong>add</strong>(other)<div class="hljs-button {2}"                                                                data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li></ul></pre></p><pre><code>    &lt;p&gt;这种风格只应用于特殊函数，比如操作符重载等。&lt;/p&gt;    &lt;p&gt;函数参数 : 小写和下划线，缺省值等号两边无空格&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span            class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(self, user=None)&lt;/span&gt;:&lt;/span&gt;</code></pre><p>self._user = user<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre></p><pre><code>    &lt;p&gt;&lt;strong&gt;（3）类&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;类总是使用驼峰格式命名，即所有单词首字母大写其余字母小写。类名应该简明，精确，并足以从中理解类所完成的工作。常见的一个方法是使用表示其类型或者特性的后缀，例如: &lt;br&gt;        SQLEngine &lt;br&gt;        MimeTypes&lt;/p&gt;    &lt;p&gt;对于基类而言，可以使用一个 Base 或者 Abstract 前缀&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;BaseCookie</code></pre><p>AbstractGroup<br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserProfile</span><span        class="hljs-params">(object)</span>:</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title"><strong>init</strong></span><span        class="hljs-params">(self, profile)</span>:</span><br><span class="hljs-keyword">return</span> self._profile = profile</p><p><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">profile</span><span        class="hljs-params">(self)</span>:</span><br><span class="hljs-keyword">return</span> self._profile<div class="hljs-button {2}" data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li                style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li                style="color: rgb(153, 153, 153);">8</li></ul></pre></p><pre><code>    &lt;h1 id=&quot;7-编码建议&quot;&gt;&lt;a name=&quot;t11&quot;&gt;&lt;/a&gt;7. 编码建议&lt;/h1&gt;    &lt;p&gt;1 编码中考虑到其他python实现的效率等问题，比如运算符‘+’在CPython（Python）中效率很高，都是Jython中却非常低，所以应该采用.join()的方式。 &lt;br&gt;        2 尽可能使用‘is’‘is not’取代‘==’，比如if x is not None 要优于if x。 &lt;br&gt;        3 使用基于类的异常，每个模块或包都有自己的异常类，此异常类继承自Exception。 &lt;br&gt;        4 异常中不要使用裸露的except，except后跟具体的exceptions。 &lt;br&gt;        5 异常中try的代码尽可能少。比如：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs cs has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;try&lt;/span&gt;:</code></pre><p><span class="hljs-keyword">value</span> = collection[key]<br>except KeyError:<br><span class="hljs-keyword">return</span> key_not_found(key)<br><span class="hljs-keyword">else</span>:<br><span class="hljs-keyword">return</span> handle_value(<span class="hljs-keyword">value</span>)<div                    class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li                style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre></p><pre><code>    &lt;p&gt;要优于&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs vala has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;try&lt;/span&gt;:</code></pre><p><span class="hljs-preprocessor"># Too broad!</span><br><span class="hljs-keyword">return</span> handle_value(collection[key])<br>except KeyError:<br><span class="hljs-preprocessor"># Will also catch KeyError raised by handle_value()</span><br><span class="hljs-keyword">return</span> key_not_found(key)<div class="hljs-button {2}" data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li                style="color: rgb(153, 153, 153);">6</li></ul></pre></p><pre><code>    &lt;p&gt;6 使用startswith() and endswith()代替切片进行序列前缀或后缀的检查。比如：&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs bash has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; foo.startswith(&lt;span            class=&quot;hljs-string&quot;&gt;&#39;bar&#39;&lt;/span&gt;):&lt;div class=&quot;hljs-button &#123;2&#125;&quot; data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul            class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;    &lt;p&gt;优于&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs bash has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt; &lt;span            class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; foo[:&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;] == &lt;span class=&quot;hljs-string&quot;&gt;&#39;bar&#39;&lt;/span&gt;:&lt;div            class=&quot;hljs-button &#123;2&#125;&quot; data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li            style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;    &lt;p&gt;7 使用isinstance()比较对象的类型。比如&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs cs has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; isinstance(obj, &lt;span            class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;): &lt;div class=&quot;hljs-button &#123;2&#125;&quot; data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul            class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;    &lt;p&gt;优于&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs haskell has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span            class=&quot;hljs-typedef&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;hljs-container&quot;&gt;(&lt;span            class=&quot;hljs-title&quot;&gt;obj&lt;/span&gt;)&lt;/span&gt; is &lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;&lt;span            class=&quot;hljs-container&quot;&gt;(1)&lt;/span&gt;:&lt;/span&gt;&lt;div class=&quot;hljs-button &#123;2&#125;&quot; data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul            class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;    &lt;p&gt;8 判断序列空或不空，有如下规则&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs ruby has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                               style=&quot;position: unset;&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span            class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;hljs-symbol&quot;&gt;seq:&lt;/span&gt;</code></pre><p><span class="hljs-keyword">if</span> <span class="hljs-symbol">seq:</span><div class="hljs-button {2}"                                                                               data-title="复制"></div></code><ul                class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                style="color: rgb(153, 153, 153);">2</li></ul></pre></p><pre><code>    &lt;p&gt;优于&lt;/p&gt;    &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs livecodeserver has-numbering&quot;                                               onclick=&quot;mdcp.copyCode(event)&quot; style=&quot;position: unset;&quot;&gt;&lt;span            class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(seq)</code></pre><p><span class="hljs-keyword">if</span> <span class="hljs-operator">not</span> <span class="hljs-built_in">len</span>(seq)<div                    class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre></p><pre><code>    &lt;p&gt;9 字符串不要以空格收尾。 &lt;br&gt;        10 二进制数据判断使用 if boolvalue的方式。&lt;/p&gt;    &lt;h1 id=&quot;8-参考文献&quot;&gt;&lt;a name=&quot;t12&quot;&gt;&lt;/a&gt;8. 参考文献&lt;/h1&gt;    &lt;p&gt;[1] PEP8中文翻译 &lt;a href=&quot;http://wiki.hiaero.net/doku.php?id=python:pep8&quot; rel=&quot;nofollow&quot;&gt;http://wiki.hiaero.net/doku.php?id=python:pep8&lt;/a&gt;        &lt;br&gt;        [2] PEP8 Python 编码规范整理 &lt;a href=&quot;https://www.douban.com/note/134971609/&quot; rel=&quot;nofollow&quot;&gt;https://www.douban.com/note/134971609/&lt;/a&gt;        &lt;br&gt;        [3] Python 代码风格 和 PEP8 &lt;a href=&quot;http://www.blogjava.net/lincode/archive/2011/02/02/343859.html&quot;                                  rel=&quot;nofollow&quot;&gt;http://www.blogjava.net/lincode/archive/2011/02/02/343859.html&lt;/a&gt;    &lt;/p&gt;&lt;/div&gt;&lt;link href=&quot;https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-b6c3c6d139.css&quot; rel=&quot;stylesheet&quot;&gt;</code></pre></div>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> standard </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python range() 和xrange()的区别</title>
      <link href="cp/python/python-range-xrange/"/>
      <url>cp/python/python-range-xrange/</url>
      
        <content type="html"><![CDATA[<div id="cnblogs_post_body" class="blogpost-body ">    <div class="cnblogs_Highlighter sh-gutter">        <div>            <div id="highlighter_834530" class="syntaxhighlighter  bash">                <div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div>                <table border="0" cellpadding="0" cellspacing="0">                    <tbody>                    <tr>                        <td class="gutter">                            <div class="line number1 index0 alt2">1</div>                            <div class="line number2 index1 alt1">2</div>                            <div class="line number3 index2 alt2">3</div>                            <div class="line number4 index3 alt1">4</div>                            <div class="line number5 index4 alt2">5</div>                            <div class="line number6 index5 alt1">6</div>                            <div class="line number7 index6 alt2">7</div>                            <div class="line number8 index7 alt1">8</div>                            <div class="line number9 index8 alt2">9</div>                            <div class="line number10 index9 alt1">10</div>                            <div class="line number11 index10 alt2">11</div>                            <div class="line number12 index11 alt1">12</div>                        </td>                        <td class="code">                            <div class="container">                                <div class="line number1 index0 alt2"><code class="bash plain">Help on                                    built-</code><code class="bash keyword">in</code> <code class="bash keyword">function</code>                                    <code class="bash plain">range </code><code class="bash keyword">in</code> <code                                            class="bash plain">module __builtin__:</code></div>                                <div class="line number2 index1 alt1">&nbsp;</div>                                <div class="line number3 index2 alt2"><code class="bash plain">range(...)</code></div>                                <div class="line number4 index3 alt1"><code                                        class="bash spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="bash plain">range(stop)                                    -&gt; list of integers</code></div>                                <div class="line number5 index4 alt2"><code                                        class="bash spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="bash plain">range(start,                                    stop[, step]) -&gt; list of integers</code></div>                                <div class="line number6 index5 alt1"><code                                        class="bash spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code>&nbsp;                                </div>                                <div class="line number7 index6 alt2"><code                                        class="bash spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="bash plain">Return                                    a list containing an arithmetic progression of integers.</code></div>                                <div class="line number8 index7 alt1"><code                                        class="bash spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="bash plain">range(i,                                    j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.</code></div>                                <div class="line number9 index8 alt2"><code                                        class="bash spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="bash plain">When                                    step is given, it specifies the increment (or decrement).</code></div>                                <div class="line number10 index9 alt1"><code class="bash spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code                                        class="bash plain">For example, range(4) returns [0, 1, 2, 3].&nbsp; The end                                    point is omitted!</code></div>                                <div class="line number11 index10 alt2"><code class="bash spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code                                        class="bash plain">These are exactly the valid indices </code><code                                        class="bash keyword">for</code> <code class="bash plain">a list of 4                                    elements.</code></div>                                <div class="line number12 index11 alt1"><code class="bash plain">(END)</code></div>                            </div>                        </td>                    </tr>                    </tbody>                </table>            </div>        </div>    </div>    <p>以上是range函数的说明，三个参数，分别代表开始，结束位置和步长。</p>    <p>使用方法如下：</p>    <div class="cnblogs_Highlighter sh-gutter">        <div>            <div id="highlighter_356591" class="syntaxhighlighter  python">                <div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div>                <table border="0" cellpadding="0" cellspacing="0">                    <tbody>                    <tr>                        <td class="gutter">                            <div class="line number1 index0 alt2">1</div>                            <div class="line number2 index1 alt1">2</div>                            <div class="line number3 index2 alt2">3</div>                            <div class="line number4 index3 alt1">4</div>                            <div class="line number5 index4 alt2">5</div>                            <div class="line number6 index5 alt1">6</div>                            <div class="line number7 index6 alt2">7</div>                            <div class="line number8 index7 alt1">8</div>                            <div class="line number9 index8 alt2">9</div>                            <div class="line number10 index9 alt1">10</div>                            <div class="line number11 index10 alt2">11</div>                            <div class="line number12 index11 alt1">12</div>                            <div class="line number13 index12 alt2">13</div>                            <div class="line number14 index13 alt1">14</div>                            <div class="line number15 index14 alt2">15</div>                            <div class="line number16 index15 alt1">16</div>                            <div class="line number17 index16 alt2">17</div>                            <div class="line number18 index17 alt1">18</div>                            <div class="line number19 index18 alt2">19</div>                            <div class="line number20 index19 alt1">20</div>                            <div class="line number21 index20 alt2">21</div>                            <div class="line number22 index21 alt1">22</div>                            <div class="line number23 index22 alt2">23</div>                            <div class="line number24 index23 alt1">24</div>                            <div class="line number25 index24 alt2">25</div>                        </td>                        <td class="code">                            <div class="container">                                <div class="line number1 index0 alt2"><code class="python plain">In [</code><code                                        class="python value">2</code><code class="python plain">]: </code><code                                        class="python functions">range</code><code class="python plain">(</code><code                                        class="python value">10</code><code class="python plain">)</code></div>                                <div class="line number2 index1 alt1"><code class="python plain">Out[</code><code                                        class="python value">2</code><code class="python plain">]: [</code><code                                        class="python value">0</code><code class="python plain">, </code><code                                        class="python value">1</code><code class="python plain">, </code><code                                        class="python value">2</code><code class="python plain">, </code><code                                        class="python value">3</code><code class="python plain">, </code><code                                        class="python value">4</code><code class="python plain">, </code><code                                        class="python value">5</code><code class="python plain">, </code><code                                        class="python value">6</code><code class="python plain">, </code><code                                        class="python value">7</code><code class="python plain">, </code><code                                        class="python value">8</code><code class="python plain">, </code><code                                        class="python value">9</code><code class="python plain">]</code></div>                                <div class="line number3 index2 alt2">&nbsp;</div>                                <div class="line number4 index3 alt1"><code class="python plain">In [</code><code                                        class="python value">3</code><code class="python plain">]: </code><code                                        class="python functions">range</code><code class="python plain">(</code><code                                        class="python value">1</code><code class="python plain">, </code><code                                        class="python value">10</code><code class="python plain">)</code></div>                                <div class="line number5 index4 alt2"><code class="python plain">Out[</code><code                                        class="python value">3</code><code class="python plain">]: [</code><code                                        class="python value">1</code><code class="python plain">, </code><code                                        class="python value">2</code><code class="python plain">, </code><code                                        class="python value">3</code><code class="python plain">, </code><code                                        class="python value">4</code><code class="python plain">, </code><code                                        class="python value">5</code><code class="python plain">, </code><code                                        class="python value">6</code><code class="python plain">, </code><code                                        class="python value">7</code><code class="python plain">, </code><code                                        class="python value">8</code><code class="python plain">, </code><code                                        class="python value">9</code><code class="python plain">]</code></div>                                <div class="line number6 index5 alt1">&nbsp;</div>                                <div class="line number7 index6 alt2"><code class="python plain">In [</code><code                                        class="python value">4</code><code class="python plain">]: </code><code                                        class="python functions">range</code><code class="python plain">(</code><code                                        class="python value">1</code><code class="python plain">, </code><code                                        class="python value">10</code><code class="python plain">, </code><code                                        class="python value">2</code><code class="python plain">)</code></div>                                <div class="line number8 index7 alt1"><code class="python plain">Out[</code><code                                        class="python value">4</code><code class="python plain">]: [</code><code                                        class="python value">1</code><code class="python plain">, </code><code                                        class="python value">3</code><code class="python plain">, </code><code                                        class="python value">5</code><code class="python plain">, </code><code                                        class="python value">7</code><code class="python plain">, </code><code                                        class="python value">9</code><code class="python plain">]</code></div>                                <div class="line number9 index8 alt2">&nbsp;</div>                                <div class="line number10 index9 alt1"><code class="python plain">In [</code><code                                        class="python value">5</code><code class="python plain">]: </code><code                                        class="python functions">type</code><code class="python plain">(</code><code                                        class="python functions">range</code><code class="python plain">(</code><code                                        class="python value">1</code><code class="python plain">, </code><code                                        class="python value">3</code><code class="python plain">))</code></div>                                <div class="line number11 index10 alt2"><code class="python plain">Out[</code><code                                        class="python value">5</code><code class="python plain">]: </code><code                                        class="python functions">list</code></div>                                <div class="line number12 index11 alt1">&nbsp;</div>                                <div class="line number13 index12 alt2"><code class="python plain">In [</code><code                                        class="python value">6</code><code class="python plain">]: </code><code                                        class="python keyword">for</code> <code class="python plain">i </code><code                                        class="python keyword">in</code> <code                                        class="python functions">range</code><code class="python plain">(</code><code                                        class="python value">10</code><code class="python plain">):</code></div>                                <div class="line number14 index13 alt1"><code                                        class="python spaces">&nbsp;&nbsp;&nbsp;</code><code class="python plain">...:&nbsp;&nbsp;&nbsp;&nbsp; </code><code                                        class="python functions">print</code> <code class="python plain">i</code></div>                                <div class="line number15 index14 alt2"><code                                        class="python spaces">&nbsp;&nbsp;&nbsp;</code><code class="python plain">...:&nbsp;&nbsp;&nbsp;&nbsp; </code>                                </div>                                <div class="line number16 index15 alt1"><code class="python value">0</code></div>                                <div class="line number17 index16 alt2"><code class="python value">1</code></div>                                <div class="line number18 index17 alt1"><code class="python value">2</code></div>                                <div class="line number19 index18 alt2"><code class="python value">3</code></div>                                <div class="line number20 index19 alt1"><code class="python value">4</code></div>                                <div class="line number21 index20 alt2"><code class="python value">5</code></div>                                <div class="line number22 index21 alt1"><code class="python value">6</code></div>                                <div class="line number23 index22 alt2"><code class="python value">7</code></div>                                <div class="line number24 index23 alt1"><code class="python value">8</code></div>                                <div class="line number25 index24 alt2"><code class="python value">9</code></div>                            </div>                        </td>                    </tr>                    </tbody>                </table>            </div>        </div>    </div>    <p>　　</p>    <p>而xrange（）说明如下：</p>    <div class="cnblogs_Highlighter sh-gutter">        <div>            <div id="highlighter_795700" class="syntaxhighlighter  bash">                <div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div>                <table border="0" cellpadding="0" cellspacing="0">                    <tbody>                    <tr>                        <td class="gutter">                            <div class="line number1 index0 alt2">1</div>                            <div class="line number2 index1 alt1">2</div>                            <div class="line number3 index2 alt2">3</div>                            <div class="line number4 index3 alt1">4</div>                            <div class="line number5 index4 alt2">5</div>                            <div class="line number6 index5 alt1">6</div>                            <div class="line number7 index6 alt2">7</div>                            <div class="line number8 index7 alt1">8</div>                            <div class="line number9 index8 alt2">9</div>                            <div class="line number10 index9 alt1">10</div>                            <div class="line number11 index10 alt2">11</div>                            <div class="line number12 index11 alt1">12</div>                            <div class="line number13 index12 alt2">13</div>                            <div class="line number14 index13 alt1">14</div>                            <div class="line number15 index14 alt2">15</div>                            <div class="line number16 index15 alt1">16</div>                            <div class="line number17 index16 alt2">17</div>                            <div class="line number18 index17 alt1">18</div>                            <div class="line number19 index18 alt2">19</div>                            <div class="line number20 index19 alt1">20</div>                            <div class="line number21 index20 alt2">21</div>                            <div class="line number22 index21 alt1">22</div>                            <div class="line number23 index22 alt2">23</div>                            <div class="line number24 index23 alt1">24</div>                            <div class="line number25 index24 alt2">25</div>                            <div class="line number26 index25 alt1">26</div>                            <div class="line number27 index26 alt2">27</div>                            <div class="line number28 index27 alt1">28</div>                            <div class="line number29 index28 alt2">29</div>                            <div class="line number30 index29 alt1">30</div>                            <div class="line number31 index30 alt2">31</div>                            <div class="line number32 index31 alt1">32</div>                            <div class="line number33 index32 alt2">33</div>                            <div class="line number34 index33 alt1">34</div>                            <div class="line number35 index34 alt2">35</div>                            <div class="line number36 index35 alt1">36</div>                            <div class="line number37 index36 alt2">37</div>                            <div class="line number38 index37 alt1">38</div>                        </td>                        <td class="code">                            <div class="container">                                <div class="line number1 index0 alt2"><code class="bash plain">Help on class                                    xrange </code><code class="bash keyword">in</code> <code class="bash plain">module                                    __builtin__:</code></div>                                <div class="line number2 index1 alt1">&nbsp;</div>                                <div class="line number3 index2 alt2"><code class="bash plain">class                                    xrange(object)</code></div>                                <div class="line number4 index3 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; xrange(stop) -&gt; xrange object</code></div>                                <div class="line number5 index4 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; xrange(start, stop[, step]) -&gt; xrange                                    object</code></div>                                <div class="line number6 index5 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number7 index6 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; Like range(), but instead of returning a list,                                    returns an object that</code></div>                                <div class="line number8 index7 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; generates the numbers </code><code                                        class="bash keyword">in</code> <code class="bash plain">the range on demand.&nbsp;                                    For looping, this is </code></div>                                <div class="line number9 index8 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; slightly faster than range() and </code><code                                        class="bash functions">more</code> <code class="bash plain">memory                                    efficient.</code></div>                                <div class="line number10 index9 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number11 index10 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; Methods defined here:</code></div>                                <div class="line number12 index11 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number13 index12 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; __getattribute__(...)</code></div>                                <div class="line number14 index13 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                    x.__getattribute__(</code><code class="bash string">'name'</code><code                                        class="bash plain">) &lt;==&gt; x.name</code></div>                                <div class="line number15 index14 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number16 index15 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; __getitem__(...)</code></div>                                <div class="line number17 index16 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x.__getitem__(y) &lt;==&gt;                                    x[y]</code></div>                                <div class="line number18 index17 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number19 index18 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; __iter__(...)</code></div>                                <div class="line number20 index19 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x.__iter__() &lt;==&gt;                                    iter(x)</code></div>                                <div class="line number21 index20 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number22 index21 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; __len__(...)</code></div>                                <div class="line number23 index22 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x.__len__() &lt;==&gt;                                    len(x)</code></div>                                <div class="line number24 index23 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number25 index24 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; __reduce__(...)</code></div>                                <div class="line number26 index25 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number27 index26 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; __repr__(...)</code></div>                                <div class="line number28 index27 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x.__repr__() &lt;==&gt;                                    repr(x)</code></div>                                <div class="line number29 index28 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number30 index29 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; __reversed__(...)</code></div>                                <div class="line number31 index30 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Returns a reverse                                    iterator.</code></div>                                <div class="line number32 index31 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number33 index32 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp;                                    ----------------------------------------------------------------------</code></div>                                <div class="line number34 index33 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; Data and other attributes defined here:</code></div>                                <div class="line number35 index34 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; </code></div>                                <div class="line number36 index35 alt1"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp; __new__ = &lt;built-</code><code                                        class="bash keyword">in</code> <code class="bash plain">method __new__                                    of </code><code class="bash functions">type</code> <code class="bash plain">object&gt;</code>                                </div>                                <div class="line number37 index36 alt2"><code class="bash spaces">&nbsp;</code><code                                        class="bash plain">|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T.__new__(S, ...) -&gt; a new                                    object with </code><code class="bash functions">type</code> <code                                        class="bash plain">S, a subtype of T</code></div>                                <div class="line number38 index37 alt1"><code class="bash plain">(END)</code></div>                            </div>                        </td>                    </tr>                    </tbody>                </table>            </div>        </div>    </div>    <p>说明了两者的区别是xrange返回的是一个可迭代的对象，range返回的则是一个列表. 同时效率更高，更快。</p>    <p>原因是实现的时候使用了yield（唔，源码没看见，具体对比可以看一下http://ju.outofmemory.cn/entry/122781），</p>    <p>因此更节省内存，规模越大区别更明显.</p>    <p>关于可迭代对象的定义见：https://eastlakeside.gitbooks.io/interpy-zh/content/Generators/Iterable.html</p>    <p>即，只要定义了可以返回一个迭代器的__iter__方法，或者__getitem__那么就是可迭代对象。</p>    <p>&nbsp;</p>    <p>xrange使用方法如下：</p>    <div class="cnblogs_Highlighter sh-gutter">        <div>            <div id="highlighter_575244" class="syntaxhighlighter  python">                <div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div>                <table border="0" cellpadding="0" cellspacing="0">                    <tbody>                    <tr>                        <td class="gutter">                            <div class="line number1 index0 alt2">1</div>                            <div class="line number2 index1 alt1">2</div>                            <div class="line number3 index2 alt2">3</div>                            <div class="line number4 index3 alt1">4</div>                            <div class="line number5 index4 alt2">5</div>                            <div class="line number6 index5 alt1">6</div>                            <div class="line number7 index6 alt2">7</div>                            <div class="line number8 index7 alt1">8</div>                            <div class="line number9 index8 alt2">9</div>                            <div class="line number10 index9 alt1">10</div>                        </td>                        <td class="code">                            <div class="container">                                <div class="line number1 index0 alt2"><code class="python plain">In [</code><code                                        class="python value">13</code><code class="python plain">]: </code><code                                        class="python functions">list</code><code class="python plain">(</code><code                                        class="python functions">xrange</code><code class="python plain">(</code><code                                        class="python value">3</code><code class="python plain">))</code></div>                                <div class="line number2 index1 alt1"><code class="python plain">Out[</code><code                                        class="python value">13</code><code class="python plain">]: [</code><code                                        class="python value">0</code><code class="python plain">, </code><code                                        class="python value">1</code><code class="python plain">, </code><code                                        class="python value">2</code><code class="python plain">]</code></div>                                <div class="line number3 index2 alt2">&nbsp;</div>                                <div class="line number4 index3 alt1"><code class="python plain">In [</code><code                                        class="python value">14</code><code class="python plain">]: a </code><code                                        class="python keyword">=</code> <code                                        class="python functions">xrange</code><code class="python plain">(</code><code                                        class="python value">3</code><code class="python plain">)</code></div>                                <div class="line number5 index4 alt2">&nbsp;</div>                                <div class="line number6 index5 alt1"><code class="python plain">In [</code><code                                        class="python value">15</code><code class="python plain">]: a.__iter__</code>                                </div>                                <div class="line number7 index6 alt2"><code class="python plain">Out[</code><code                                        class="python value">15</code><code class="python plain">]:                                    &lt;method</code><code class="python keyword">-</code><code class="python plain">wrapper </code><code                                        class="python string">'__iter__'</code> <code                                        class="python plain">of </code><code class="python functions">xrange</code>                                    <code class="python functions">object</code> <code                                            class="python plain">at </code><code                                            class="python value">0x7f415be1bdc8</code><code                                            class="python plain">&gt;</code></div>                                <div class="line number8 index7 alt1">&nbsp;</div>                                <div class="line number9 index8 alt2"><code class="python plain">In [</code><code                                        class="python value">16</code><code class="python plain">]: a.__iter__()</code>                                </div>                                <div class="line number10 index9 alt1"><code class="python plain">Out[</code><code                                        class="python value">16</code><code class="python plain">]: &lt;rangeiterator                                    at </code><code class="python value">0x7f415aa27210</code><code                                        class="python plain">&gt;</code></div>                            </div>                        </td>                    </tr>                    </tbody>                </table>            </div>        </div>    </div>    <p>　　</p>    <p>　</p>    <p>　　</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中的垃圾回收机制</title>
      <link href="cp/python/python-recycling-mechanism/"/>
      <url>cp/python/python-recycling-mechanism/</url>
      
        <content type="html"><![CDATA[<div class="RichText ztext Post-RichText"><h2>一、概述</h2>    <p>python采用的是<b>引用计数</b>机制为主，<b>标记-清除</b>和<b>分代收集（隔代回收）</b>两种机制为辅的策略。<br></p>    <blockquote>        现在的高级语言如java，c#等，都采用了垃圾收集机制，而不再是c，c++里用户自己管理维护内存的方式。自己管理内存极其自由，可以任意申请内存，但如同一把双刃剑，为大量内存泄露，悬空指针等bug埋下隐患。<br>对于一个字符串、列表、类甚至数值都是对象，且定位简单易用的语言，自然不会让用户去处理如何分配回收内存的问题。<br>python里也同java一样采用了垃圾收集机制，不过不一样的是:<br>python采用的是引用计数机制为主，标记-清除和分代收集（隔代回收）两种机制为辅的策略。    </blockquote>    <h2>二、引用计数机制</h2>    <blockquote>        引用计数法机制的原理是：每个对象维护一个ob_ref字段，用来记录该对象当前被引用的次数，每当新的引用指向该对象时，它的引用计数ob_ref加1，每当该对象的引用失效时计数ob_ref减1，一旦对象的引用计数为0，该对象立即被回收，对象占用的内存空间将被释放。它的缺点是需要额外的空间维护引用计数，这个问题是其次的，不过最主要的问题是它不能解决对象的“循环引用”，因此，也有很多语言比如Java并没有采用该算法做来垃圾的收集机制。    </blockquote>    <p>python里每一个东西都是对象，它们的核心就是一个结构体：PyObject</p>    <p>PyObject是每个对象必有的内容，其中ob_refcnt就是做为引用计数。当一个对象有新的引用时，它的ob_refcnt就会增加，当引用它的对象被删除，它的ob_refcnt就会减少</p>    <p>引用计数为0时，该对象生命就结束了。</p>    <p><b>引用计数机制的优点：</b></p>    <p>1、简单</p>    <p>2、实时性：一旦没有引用，内存就直接释放了，不用像其他机制得等到特定时机。实时性还带来一个好处：处理回收内存的时间分摊到了平时。</p>    <p><b>引用计数机制的缺点：</b></p>    <p>1、维护引用计数消耗资源</p>    <p>2、循环引用</p>    <p><b>案例：</b></p>    <div class="highlight"><pre><code class="language-python3"><span class="kn">import</span> <span            class="nn">sys</span><span class="k">class</span> <span class="nc">A</span><span class="p">():</span>    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span                class="p">):</span>        <span class="s1">'''初始化对象'''</span>        <span class="nb">print</span><span class="p">(</span><span class="s1">'object born id:</span><span                class="si">%s</span><span class="s1">'</span> <span class="o">%</span><span class="nb">str</span><span                class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="nb">id</span><span                class="p">(</span><span class="bp">self</span><span class="p">))))</span><p><span class="k">def</span> <span class="nf">f1</span><span class="p">():</span><br>    <span class="s1">‘’’循环引用变量与删除变量’’’</span><br>    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span><br>        <span class="n">c1</span><span class="o">=</span><span class="n">A</span><span class="p">()</span><br>        <span class="k">del</span> <span class="n">c1</span></p><p><span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">c</span><span class="p">):</span><br>    <span class="nb">print</span><span class="p">(</span><span class="s1">‘obejct refcount is: ‘</span><span                class="p">,</span><span class="n">sys</span><span class="o">.</span><span                class="n">getrefcount</span><span class="p">(</span><span class="n">c</span><span                class="p">))</span> <span class="c1">#getrefcount()方法用于返回对象的引用计数</span></p><p><span class="k">if</span> <span class="vm"><strong>name</strong></span> <span class="o">==</span> <span                class="s1">‘<strong>main</strong>‘</span><span class="p">:</span><br>   <span class="c1">#生成对象</span><br>    <span class="n">a</span><span class="o">=</span><span class="n">A</span><span class="p">()</span><br>    <span class="n">func</span><span class="p">(</span><span class="n">a</span><span class="p">)</span></p><pre><code>&lt;span class=&quot;c1&quot;&gt;#增加引用&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#销毁引用对象b&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;</code></pre><p><span class="c1">#结果</span><br><span class="nb">object</span> <span class="n">born</span> <span class="nb">id</span><span class="p">:</span><span                class="mh">0x19f5ecb9320</span><br><span class="n">obejct</span> <span class="n">refcount</span> <span class="ow">is</span><span class="p">:</span>  <span                class="mi">4</span><br><span class="n">obejct</span> <span class="n">refcount</span> <span class="ow">is</span><span class="p">:</span>  <span                class="mi">5</span><br><span class="n">obejct</span> <span class="n">refcount</span> <span class="ow">is</span><span class="p">:</span>  <span                class="mi">4</span></code></pre><br>    </div><br>    <h3><b>导致引用计数+1的情况</b></h3><br>    <ul><br>        <li>对象被创建，例如a=23</li><br>        <li>对象被引用，例如b=a</li><br>        <li>对象被作为参数，传入到一个函数中，例如<code>func(a)</code></li><br>        <li>对象作为一个元素，存储在容器中，例如<code>list1=[a,a]</code></li><br>    </ul><br>    <h3><b>导致引用计数-1的情况</b></h3><br>    <ul><br>        <li>对象的别名被显式销毁，例如<code>del a</code></li><br>        <li>对象的别名被赋予新的对象，例如<code>a=24</code></li><br>        <li>一个对象离开它的作用域，例如:func函数执行完毕时，func函数中的局部变量（全局变量不会）</li><br>        <li>对象所在的容器被销毁，或从容器中删除对象</li><br>    </ul><br>    <p><b>循环引用导致内存泄露</b></p><br>    <div class="highlight"><pre><code class="language-text">def f2():<br>    '''循环引用'''<br>    while True:<br>        c1=A()<br>        c2=A()<br>        c1.t=c2<br>        c2.t=c1<br>        del c1<br>        del c2</code></pre><br>    </div><br>    <ul><br>        <li>创建了<code>c1</code>，<code>c2</code>后，这两个对象的引用计数都是<code>1</code>，执行<code>c1.t=c2</code>和<code>c2.t=c1</code>后，引用计数变成<code>2</code>.<br>        </li><br>        <li>在<code>del c1</code>后，内存<code>c1</code>的对象的引用计数变为<code>1</code>，由于不是为<code>0</code>，所以<code>c1</code>的对象不会被销毁,同理，在<code>del<br>            c2</code>后也是一样的。<br>        </li><br>        <li>虽然它们两个的对象都是可以被销毁的，但是由于循环引用，导致垃圾回收器都不会回收它们，所以就会导致内存泄露。</li><br>    </ul><br>    <p class="ztext-empty-paragraph"><br></p><br>    <h3><b>分代回收</b></h3><br>    <ul><br>        <li><br>            分代回收是一种以空间换时间的操作方式，Python将内存根据对象的存活时间划分为不同的集合，每个集合称为一个代，Python将内存分为了3“代”，分别为年轻代（第0代）、中年代（第1代）、老年代（第2代），他们对应的是3个链表，它们的垃圾收集频率随着对象存活时间的增大而减小。<br>        </li><br>        <li><br>            新创建的对象都会分配在<b>年轻代</b>，年轻代链表的总数达到上限时，Python垃圾收集机制就会被触发，把那些可以被回收的对象回收掉，而那些不会回收的对象就会被移到<b>中年代</b>去，依此类推，<b>老年代</b>中的对象是存活时间最久的对象，甚至是存活于整个系统的生命周期内。<br>        </li><br>        <li>同时，分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象</li><br>    </ul><br>    <h3><b>垃圾回收</b></h3><br>    <p>有三种情况会触发垃圾回收：</p><br>    <ol><br>        <li>调用<code>gc.collect()</code>,需要先导入<code>gc</code>模块。</li><br>        <li>当<code>gc</code>模块的计数器达到阈值的时候。</li><br>        <li>程序退出的时候。</li><br>    </ol><br>    <h3><b>gc模块</b></h3><br>    <p>gc模块提供一个接口给开发者设置垃圾回收的选项。上面说到，采用引用计数的方法管理内存的一个缺陷是循环引用，而gc模块的一个主要功能就是解决循环引用的问题。</p><br>    <p><b>常用函数</b>：</p><br>    <ol><br>        <li><code>gc.set_debug(flags)</code> 设置gc的debug日志，一般设置为<code>gc.DEBUG_LEAK</code></li><br>        <li><code>gc.collect([generation])</code> <br>显式进行垃圾回收，可以输入参数，<code>0</code>代表只检查第一代的对象，<code>1</code>代表检查一，二代的对象，<code>2</code>代表检查一，二，三代的对象，如果不传参数，执行一个<code>full<br>            collection</code>，也就是等于传2。返回不可达（unreachable objects）对象的数目。<br>        </li><br>        <li><code>gc.set_threshold(threshold0[, threshold1[, threshold2])</code><br>设置自动执行垃圾回收的频率。</li><br>        <li><code>gc.get_count()</code> 获取当前自动执行垃圾回收的计数器，返回一个长度为3的列表</li><br>    </ol><br>    <p><b>gc实践案例</b></p><br>    <div class="highlight"><pre><code class="language-text">def f3():<br>    '''循环引用'''<br>    while True:<br>        c1=A()<br>        c2=A()<br>        c1.t=c2<br>        c2.t=c1<br>        del c1<br>        del c2<br>        #增加垃圾回收机制<br>        print(gc.garbage)<br>        print(gc.collect())<br>        print(gc.garbage)<br>        time.sleep(10)<br>#结果<br>object born id:0x21d1a5dc470<br>object born id:0x21d1a5dc9e8<br>[]<br>4<br>gc: collectable &lt;A 0x0000021D1A5DC470&gt;<br>[&lt;<strong>main</strong>.A object at 0x0000021D1A5DC470&gt;, &lt;<strong>main</strong>.A object at 0x0000021D1A5DC9E8&gt;, &#123;'t': &lt;<strong>main</strong>.A object at 0x0000021D1A5DC9E8&gt;&#125;, &#123;'t': &lt;<strong>main</strong>.A object at 0x0000021D1A5DC470&gt;&#125;]<br>gc: collectable &lt;A 0x0000021D1A5DC9E8&gt;<br>gc: collectable &lt;dict 0x0000021D1A156C88&gt;<br>gc: collectable &lt;dict 0x0000021D1A5CABC8&gt;</code></pre><br>    </div><br>    <h3><b>gc模块的自动垃圾回收机制</b></h3><br>    <p>必须要import gc模块，并且is_enable()=True才会启动自动垃圾回收。<br>这个机制的主要作用就是发现并处理不可达的垃圾对象。</p><br>    <blockquote>垃圾回收=垃圾检查+垃圾回收</blockquote><br>    <p>在Python中，采用分代收集的方法。把对象分为三代，一开始，对象在创建的时候，放在一代中，如果在一次一代的垃圾检查中，该对象存活下来，就会被放到二代中，同理在一次二代的垃圾检查中，该对象存活下来，就会被放到三代中。</p><br>    <p>gc模块里面会有一个长度为3的列表的计数器，可以通过<code>gc.get_count()</code>获取。</p><br>    <div class="highlight"><pre><code class="language-text">def f4():<br>    '''垃圾自动回收'''<br>    print(gc.get_count())<br>    a=A()<br>    print(gc.get_count())<br>    del a<br>    print(gc.get_count())<br>#结果<br>(621, 10, 0)<br>object born id:0x2ca32a8c588<br>(624, 10, 0)<br>(623, 10, 0)</code></pre><br>    </div><br>    <ul><br>        <li><code>621</code>指距离上一次<code>一代</code>垃圾检查，Python分配内存的数目减去释放内存的数目，注意:是内存分配，而不是引用计数的增加。</li><br>        <li><code>10</code>指距离上一次<code>二代</code>垃圾检查，<code>一代</code>垃圾检查的次数。</li><br>        <li><code>0</code>是指距离上一次<code>三代</code>垃圾检查，<code>二代</code>垃圾检查的次数。</li><br>    </ul><br>    <h3><b>自动回收阈值</b></h3><br>    <p>gc模快有一个自动垃圾回收的阀值，即通过<code>gc.get_threshold</code>函数获取到的长度为3的元组，例如<code>(700,10,10)</code><br>每一次计数器的增加，gc模块就会检查增加后的计数是否达到阀值的数目，如果是，就会执行对应的代数的垃圾检查，然后重置计数器<br>    </p><br>    <p>注意：<br>如果循环引用中，两个对象都定义了<code><strong>del</strong></code>方法，gc模块不会销毁这些不可达对象，因为gc模块不知道应该先调用哪个对象的<code><strong>del</strong></code>方法，所以为了安全起见，gc模块会把对象放到<code>gc.garbage</code>中，但是不会销毁对象。<br>    </p><br>    <h3><b>标记清除</b></h3><br>    <p>标记清除（Mark—Sweep）』算法是一种基于追踪回收（tracing<br>        GC）技术实现的垃圾回收算法。它分为两个阶段：第一阶段是标记阶段，GC会把所有的『活动对象』打上标记，第二阶段是把那些没有标记的对象『非活动对象』进行回收。那么GC又是如何判断哪些是活动对象哪些是非活动对象的呢？</p><br>    <figure data-size="normal"><br>        <noscript><img src= "/img/loading.gif" data-lazy-src="https://pic1.zhimg.com/v2-543bb871b0eb79e4b6b9186ac1588e34_b.jpg" data-caption=""                       data-size="normal" data-rawwidth="328" data-rawheight="250" class="content_image" width="328"/><br>        </noscript><br>        <img src= "/img/loading.gif" data-lazy-src="https://pic1.zhimg.com/80/v2-543bb871b0eb79e4b6b9186ac1588e34_hd.jpg" data-caption=""             data-size="normal" data-rawwidth="328" data-rawheight="250" class="content_image lazy" width="328"             data-actualsrc="https://pic1.zhimg.com/v2-543bb871b0eb79e4b6b9186ac1588e34_b.jpg" data-lazy-status="ok"><br>    </figure><br>    <p class="ztext-empty-paragraph"><br></p><br>    <p>对象之间通过引用（指针）连在一起，构成一个有向图，对象构成这个有向图的节点，而引用关系构成这个有向图的边。从根对象（root<br>        object）出发，沿着有向边遍历对象，可达的（reachable）对象标记为活动对象，不可达的对象就是要被清除的非活动对象。根对象就是全局变量、调用栈、寄存器。 mark-sweepg<br>        在上图中，我们把小黑圈视为全局变量，也就是把它作为root<br>        object，从小黑圈出发，对象1可直达，那么它将被标记，对象2、3可间接到达也会被标记，而4和5不可达，那么1、2、3就是活动对象，4和5是非活动对象会被GC回收。</p><br>    <p><br>        标记清除算法作为Python的辅助垃圾收集技术主要处理的是一些容器对象，比如list、dict、tuple，instance等，因为对于字符串、数值对象是不可能造成循环引用问题。Python使用一个双向链表将这些容器对象组织起来。不过，这种简单粗暴的标记清除算法也有明显的缺点：清除非活动的对象前它必须顺序扫描整个堆内存，哪怕只剩下小部分活动对象也要扫描所有对象。</p></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python3中的反射详解</title>
      <link href="cp/python/python-reflect/"/>
      <url>cp/python/python-reflect/</url>
      
        <content type="html"><![CDATA[<p>相信很多人和我一样第一次听到<code>反射</code>这个词语是特别陌生的，再次之前我最熟悉的还是c语言，但是在c语言中并没有反射这种机制。<br>    c++中原生并不支持反射机制，但是Java中是支持的。在高级的Python中当然也是支持的。</p><h1>什么是反射？</h1><p>说到反射，我并不想用很多专业晦涩难懂的词语，因为也不是很懂害怕出错，如果那里有错还请指正。</p><p>相信我们是经常使用浏览器的，在使用浏览器的时候最重要的也不就是输入网址了，在浏览器的地址栏中输入对应的网址，对应的网站也就会有反应，并给你返回对应的网页。首相我们要知道，我们输入到浏览器地址栏的<code>url</code>是一个字符串，这个字符串的<code>url</code>到web服务器上后是怎么找到对应的代码函数并执行后给我们返回内容的。</p><p>比如：现在我们有这样一个需求，已知有三个函数<code>fun1</code>, <code>fun2</code>, <code>fun3</code>这三个函数，我们都找到如果我们想调用其中某个函数的时候，我们就只有在代码中写好，比如我写了一个这样的代码来实现这个功能：</p><p>首先在文件项目下创建两个文件：<code>test.py</code>, <code>s.py</code>这两个python文件</p><div class="image-package">    <div class="image-container" style="max-width: 700px; max-height: 414px; background-color: transparent;">        <div class="image-container-fill" style="padding-bottom: 37.3%;"></div>        <div class="image-view" data-width="1110" data-height="414"><img                data-original-src="//upload-images.jianshu.io/upload_images/13859457-3c31dd82c446cc0e.png"                data-original-width="1110" data-original-height="414" data-original-format="image/png"                data-original-filesize="72108" class="" data-image-index="0" style="cursor: zoom-in;"                src="//upload-images.jianshu.io/upload_images/13859457-3c31dd82c446cc0e.png?imageMogr2/auto-orient/strip|imageView2/2/w/1110/format/webp">        </div>    </div>    <div class="image-caption"></div></div><p><code>s.py</code>,代码如下：</p><pre class="line-numbers  language-python"><code class="  language-python"><span        class="token keyword">def</span> <span class="token function">fun2</span><span        class="token punctuation">(</span><span class="token punctuation">)</span><span        class="token punctuation">:</span>    <span class="token keyword">return</span> <span class="token string">"fun2"</span><p><span class="token keyword">def</span> <span class="token function">fun1</span><span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token string">‘fun1’</span></p><p><span class="token keyword">def</span> <span class="token function">fun3</span><span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">:</span><br>    <span class="token keyword">return</span> <span class="token string">‘fun3’</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p><code>test.py</code>，代码如下：</p><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">import</span> s  <span        class="token comment">#导入s.py文件。</span><p>call_str <span class="token operator">=</span> <span class="token builtin">input</span><span            class="token punctuation">(</span><span            class="token string">“input which function you want to call :”</span><span            class="token punctuation">)</span></p><p><span class="token keyword">if</span> call_str <span class="token operator">==</span> <span            class="token string">‘fun1’</span><span class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun1<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">elif</span> call_str <span class="token operator">==</span> <span class="token string">‘fun2’</span><span            class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun2<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">elif</span> call_str <span class="token operator">==</span> <span class="token string">‘fun3’</span><span            class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun3<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">else</span><span class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">“404 not Found”</span><span            class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>    运行文件<code>test.py</code>后输入对应的函数名就可以调用相应的函数了。如果在<code>s.py</code>文件中，有上千个函数呢！岂不是我想像以上方式调用的时候得写上千个判断语句，这样是不是太麻烦了。<br>    所以python给我们提供了强大的反射机制，这个反射机制是通过<code>字符串返回映射到代码中的一种机制</code>。<br>    这便是反射的意思了，如果你还不是很明白还可以继续百度，参考其他的写的文章了。</p><h1>python怎样使用反射</h1><p>首先，python给我嗯提供了四个关于反射的四个内置函数分别是：</p><ol>    <li><code>getattr</code></li>    <li><code>setattr</code></li>    <li><code>delattr</code></li>    <li><code>hasattr</code></li></ol><p>下面我们简单的学习下这四个函数的有关用法：<br>    在上面我是用if判断语句来实现函数的调用，这里我使用<code>getattr</code>的方法来调用，在<code>test.py</code>中增加代码如下：</p><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">import</span> s<p>call_str <span class="token operator">=</span> <span class="token builtin">input</span><span            class="token punctuation">(</span><span            class="token string">“input which function you want to call :”</span><span            class="token punctuation">)</span></p><p><span class="token keyword">if</span> call_str <span class="token operator">==</span> <span            class="token string">‘fun1’</span><span class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun1<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">elif</span> call_str <span class="token operator">==</span> <span class="token string">‘fun2’</span><span            class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun2<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">elif</span> call_str <span class="token operator">==</span> <span class="token string">‘fun3’</span><span            class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun3<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">else</span><span class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">“404 not Found”</span><span            class="token punctuation">)</span></p><p>obj <span class="token operator">=</span> <span class="token builtin">getattr</span><span            class="token punctuation">(</span>s<span class="token punctuation">,</span> call_str<span            class="token punctuation">)</span> <span class="token comment"># 其中的s是值的带入的s文件，s也可以换为其他的你想倒入的模块等</span><br><span class="token keyword">print</span><span class="token punctuation">(</span>obj<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>运行后我们输入 <code>fun1</code>, <code>fun2</code>, <code>fun3</code>都没有问题，但是当我们乱输入一个字符串的时候<code>getattr</code>内置函数就报如下的错误：<br>    <code>module 's' has no attribute 'asf'</code></p><p>怎么解决这个问题呢？我们就可以使用<code>hasattr</code>这一个内置函数了：</p><pre class="line-numbers  language-python"><code class="  language-python"><span class="token keyword">import</span> s<p>call_str <span class="token operator">=</span> <span class="token builtin">input</span><span            class="token punctuation">(</span><span            class="token string">“input which function you want to call :”</span><span            class="token punctuation">)</span></p><p><span class="token keyword">if</span> call_str <span class="token operator">==</span> <span            class="token string">‘fun1’</span><span class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun1<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">elif</span> call_str <span class="token operator">==</span> <span class="token string">‘fun2’</span><span            class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun2<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">elif</span> call_str <span class="token operator">==</span> <span class="token string">‘fun3’</span><span            class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>s<span            class="token punctuation">.</span>fun3<span class="token punctuation">(</span><span            class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token keyword">else</span><span class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">“404 not Found”</span><span            class="token punctuation">)</span></p><p><span class="token keyword">if</span> <span class="token builtin">hasattr</span><span class="token punctuation">(</span>s<span            class="token punctuation">,</span> call_str<span class="token punctuation">)</span><span            class="token punctuation">:</span>    <span class="token comment"># 判断是否存在函数 call_str，这样处理就不会报错了。</span><br>    obj <span class="token operator">=</span> <span class="token builtin">getattr</span><span class="token punctuation">(</span>s<span            class="token punctuation">,</span> call_str<span class="token punctuation">)</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span>obj<span            class="token punctuation">(</span><span class="token punctuation">)</span><span            class="token punctuation">)</span><br><span class="token keyword">else</span><span class="token punctuation">:</span><br>    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">“404 not Found”</span><span            class="token punctuation">)</span><br><span aria-hidden="true"      class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code><button        class="VJbwyy" type="button" aria-label="复制代码"><i aria-label="icon: copy" class="anticon anticon-copy"><svg        viewBox="64 64 896 896" focusable="false" class="" data-icon="copy" width="1em" height="1em"        fill="currentColor" aria-hidden="true"><path        d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></pre></p><p>当然<code>setattr</code>和<code>delattr</code>,也分别是设置和删除功能。<br>    如果你对面对对象比较熟悉的话，你就能很容易的理解到了，这里的四个函数也是可以分别对对象进行操作的。</p>    <p>原文链接:<a href="https://www.jianshu.com/p/f6d82f6226cf">https://www.jianshu.com/p/f6d82f6226cf</a><br>推荐参考:<a href="https://www.jianshu.com/p/1fcea924e71f">https://www.jianshu.com/p/1fcea924e71f</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>​Python3新特性：类型注解</title>
      <link href="cp/python/python-type-annotation/"/>
      <url>cp/python/python-type-annotation/</url>
      
        <content type="html"><![CDATA[<div class="RichText ztext Post-RichText">    <p>前几天有同学问到，这个写法是什么意思：</p>    <div class="highlight"><pre><code class="language-python3"><span class="k">def</span> <span            class="nf">add</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span            class="nb">int</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span><span            class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span            class="p">:</span>    <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span                class="n">y</span></code></pre>    </div>    <p>我们知道 Python 是一种动态语言，变量以及函数的参数是<b>不区分类型</b>。因此我们定义函数只需要这样写就可以了：</p>    <div class="highlight"><pre><code class="language-python3"><span class="k">def</span> <span            class="nf">add</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span            class="n">y</span><span class="p">):</span>    <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span                class="n">y</span></code></pre>    </div>    <p>这样的好处是有极大的灵活性，但坏处就是对于别人代码，无法一眼判断出参数的类型，IDE 也无法给出正确的提示。</p>    <p>于是 Python 3 提供了一个新的特性：<br><b>函数注解</b></p>    <p>也就是文章开头的这个例子：</p>    <div class="highlight"><pre><code class="language-python3"><span class="k">def</span> <span            class="nf">add</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span            class="nb">int</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span><span            class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span            class="p">:</span>    <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span                class="n">y</span></code></pre>    </div>    <p>用 <code>: 类型</code> 的形式指定函数的<b>参数类型</b>，用 <code>-&gt; 类型</code> 的形式指定函数的<b>返回值</b>类型。</p>    <p>然后特别要强调的是，Python 解释器<b>并不会</b>因为这些注解而提供额外的校验，没有任何的类型检查工作。也就是说，这些类型注解加不加，对你的代码来说<b>没有任何影响</b>：</p>    <figure data-size="normal">        <noscript><img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/v2-9b87d43afdc941929c428b03865037c3_b.jpg" data-caption=""                       data-size="normal" data-rawwidth="1064" data-rawheight="530"                       class="origin_image zh-lightbox-thumb" width="1064"                       data-original="https://pic4.zhimg.com/v2-9b87d43afdc941929c428b03865037c3_r.jpg"/></noscript>        <img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/80/v2-9b87d43afdc941929c428b03865037c3_hd.jpg" data-caption=""             data-size="normal" data-rawwidth="1064" data-rawheight="530" class="origin_image zh-lightbox-thumb lazy"             width="1064" data-original="https://pic4.zhimg.com/v2-9b87d43afdc941929c428b03865037c3_r.jpg"             data-actualsrc="https://pic4.zhimg.com/v2-9b87d43afdc941929c428b03865037c3_b.jpg" data-lazy-status="ok">    </figure>    <p>输出：</p>    <figure data-size="normal">        <noscript><img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/v2-f00b176bddec7e1d242e3c0e13f30f33_b.jpg" data-caption=""                       data-size="normal" data-rawwidth="486" data-rawheight="202"                       class="origin_image zh-lightbox-thumb" width="486"                       data-original="https://pic4.zhimg.com/v2-f00b176bddec7e1d242e3c0e13f30f33_r.jpg"/></noscript>        <img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/80/v2-f00b176bddec7e1d242e3c0e13f30f33_hd.jpg" data-caption=""             data-size="normal" data-rawwidth="486" data-rawheight="202" class="origin_image zh-lightbox-thumb lazy"             width="486" data-original="https://pic4.zhimg.com/v2-f00b176bddec7e1d242e3c0e13f30f33_r.jpg"             data-actualsrc="https://pic4.zhimg.com/v2-f00b176bddec7e1d242e3c0e13f30f33_b.jpg" data-lazy-status="ok">    </figure>    <p>但这么做的好处是：</p>    <ol>        <li>让别的程序员看得更明白</li>        <li>让 IDE 了解类型，从而提供更准确的代码提示、补全和语法检查（包括类型检查，可以看到 str 和 float 类型的参数被高亮提示）</li>    </ol>    <figure data-size="normal">        <noscript><img src= "/img/loading.gif" data-lazy-src="https://pic2.zhimg.com/v2-057629e3d59552c856dba7341882ea55_b.jpg" data-caption=""                       data-size="normal" data-rawwidth="1080" data-rawheight="631"                       class="origin_image zh-lightbox-thumb" width="1080"                       data-original="https://pic2.zhimg.com/v2-057629e3d59552c856dba7341882ea55_r.jpg"/></noscript>        <img src= "/img/loading.gif" data-lazy-src="https://pic2.zhimg.com/80/v2-057629e3d59552c856dba7341882ea55_hd.jpg" data-caption=""             data-size="normal" data-rawwidth="1080" data-rawheight="631" class="origin_image zh-lightbox-thumb lazy"             width="1080" data-original="https://pic2.zhimg.com/v2-057629e3d59552c856dba7341882ea55_r.jpg"             data-actualsrc="https://pic2.zhimg.com/v2-057629e3d59552c856dba7341882ea55_b.jpg" data-lazy-status="ok">    </figure>    <p>在函数的 <code>__annotations__</code> 属性中会有你设定的注解：</p>    <figure data-size="normal">        <noscript><img src= "/img/loading.gif" data-lazy-src="https://pic1.zhimg.com/v2-9a9f55559930501472752996a3b772a4_b.jpg" data-caption=""                       data-size="normal" data-rawwidth="1004" data-rawheight="306"                       class="origin_image zh-lightbox-thumb" width="1004"                       data-original="https://pic1.zhimg.com/v2-9a9f55559930501472752996a3b772a4_r.jpg"/></noscript>        <img src= "/img/loading.gif" data-lazy-src="https://pic1.zhimg.com/80/v2-9a9f55559930501472752996a3b772a4_hd.jpg" data-caption=""             data-size="normal" data-rawwidth="1004" data-rawheight="306" class="origin_image zh-lightbox-thumb lazy"             width="1004" data-original="https://pic1.zhimg.com/v2-9a9f55559930501472752996a3b772a4_r.jpg"             data-actualsrc="https://pic1.zhimg.com/v2-9a9f55559930501472752996a3b772a4_b.jpg" data-lazy-status="ok">    </figure>    <p>输出：</p>    <figure data-size="normal">        <noscript><img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/v2-35506981e2c4f0e021b4b0902e36441b_b.jpg" data-caption=""                       data-size="normal" data-rawwidth="1080" data-rawheight="57"                       class="origin_image zh-lightbox-thumb" width="1080"                       data-original="https://pic4.zhimg.com/v2-35506981e2c4f0e021b4b0902e36441b_r.jpg"/></noscript>        <img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/80/v2-35506981e2c4f0e021b4b0902e36441b_hd.jpg" data-caption=""             data-size="normal" data-rawwidth="1080" data-rawheight="57" class="origin_image zh-lightbox-thumb lazy"             width="1080" data-original="https://pic4.zhimg.com/v2-35506981e2c4f0e021b4b0902e36441b_r.jpg"             data-actualsrc="https://pic4.zhimg.com/v2-35506981e2c4f0e021b4b0902e36441b_b.jpg" data-lazy-status="ok">    </figure>    <p>在 Python 3.6 中，又引入了对<b>变量类型</b>进行注解的方法：</p>    <div class="highlight"><pre><code class="language-python3"><span class="n">a</span><span class="p">:</span> <span            class="nb">int</span> <span class="o">=</span> <span class="mi">123</span><span class="n">b</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s1">'hello'</span></code></pre>    </div>    <p>更进一步，如果你需要指明一个全部由整数组成的列表：</p>    <div class="highlight"><pre><code class="language-python3"><span class="kn">from</span> <span            class="nn">typing</span> <span class="k">import</span> <span class="n">List</span><span class="n">l</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span                class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span                class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span                class="mi">3</span><span class="p">]</span></code></pre>    </div>    <p>但同样，这些仅仅是“<b>注解</b>”，不会对代码产生任何影响。</p>    <p>不过，你可以通过 <b>mypy</b> 库来检验最终代码是否符合注解。</p>    <p>安装 mypy：</p>    <div class="highlight">        <pre><code class="language-bash">pip install mypy</code></pre>    </div>    <p>执行代码：</p>    <div class="highlight">        <pre><code class="language-bash">mypy test.py</code></pre>    </div>    <p>如果类型都符合，则不会有任何输出，否则就会给出类似输出：</p>    <figure data-size="normal">        <noscript><img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/v2-57b0ba00b7e95b092ae6fd6acc50eb37_b.jpg" data-caption=""                       data-size="normal" data-rawwidth="1076" data-rawheight="58"                       class="origin_image zh-lightbox-thumb" width="1076"                       data-original="https://pic4.zhimg.com/v2-57b0ba00b7e95b092ae6fd6acc50eb37_r.jpg"/></noscript>        <img src= "/img/loading.gif" data-lazy-src="https://pic4.zhimg.com/80/v2-57b0ba00b7e95b092ae6fd6acc50eb37_hd.jpg" data-caption=""             data-size="normal" data-rawwidth="1076" data-rawheight="58" class="origin_image zh-lightbox-thumb lazy"             width="1076" data-original="https://pic4.zhimg.com/v2-57b0ba00b7e95b092ae6fd6acc50eb37_r.jpg"             data-actualsrc="https://pic4.zhimg.com/v2-57b0ba00b7e95b092ae6fd6acc50eb37_b.jpg" data-lazy-status="ok">    </figure>    <p>这些新特性也许你并不会在代码中使用，不过当你在别人的代码中看到时，请按照对方的约定进行赋值或调用。</p>    <p>当然，也不排除 Python 以后的版本把类型检查做到解释器里，谁知道呢。</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python2版本和python3的区别</title>
      <link href="cp/python/python2-python3/"/>
      <url>cp/python/python2-python3/</url>
      
        <content type="html"><![CDATA[<h3 id="print-函数"><a href="#print-函数" class="headerlink" title="print 函数:"></a>print 函数:</h3><p>这个函数其实很简单，区别也很直接，不过网上讲的是真专业。。我们知道Python2.6和Python2.7是过渡版本，这些是可以兼容一部分Python3的语法的，print（）是在Python3常用版本，Python2是不用加括号和加括号兼容的。</p><p>我们说的像print简单的区别就是后面加上了括号，其实更确切的说是把print语句变成了print()函数。这个加不加括号直接决定了是函数还是语句的区别。在类里面是属性和方法的区别。大家注意一下就好。</p><h3 id="Unicode："><a href="#Unicode：" class="headerlink" title="Unicode："></a>Unicode：</h3><p>Python 2 有 ASCII str() 类型，unicode() 是单独的，不是 byte 类型。现在 Python 3，我们最终有了 Unicode (utf-8) 字符串，以及一个字节类：byte 和bytearrays。由于 Python3.X 源码文件默认使用utf-8编码</p><p>所以以前在用Python2的时候总是要在文件的第一行加上一行注释：</p><h3 id="Unicode：-1"><a href="#Unicode：-1" class="headerlink" title="Unicode："></a>Unicode：</h3><p>Python 2 有 ASCII str() 类型，unicode() 是单独的，不是 byte 类型。现在 Python 3，我们最终有了 Unicode (utf-8) 字符串，以及一个字节类：byte 和bytearrays。由于 Python3.X 源码文件默认使用utf-8编码</p><p>所以以前在用Python2的时候总是要在文件的第一行加上一行注释：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#! usr/bin/python </span></span><br><span class="line"><span class="comment">#coding=utf-8</span></span><br></pre></td></tr></table></figure><p>也就是说需要我们制定编码格式，要不然对中文很不友好。但是Python3是很好的编码方式，输入中文很方便，但是我们在看见大牛还在Python3加这句话的时候不要笑，他可能很了解Python2已经养成了习惯而已。</p><h3 id="除法运算："><a href="#除法运算：" class="headerlink" title="除法运算："></a>除法运算：</h3><p>Python中的除法较其它语言显得非常高端，有套很复杂的规则。（没有学习其他语言，不知道高端在哪），Python中的除法有两个运算符，/和//（整除也加地板除），区别就在/</p><p>在Python2.x版本给人的感觉有点死板，这也是我比较喜欢Python3的原因，他越来越摆脱关于程序的死磕，有着一些类似“智能”的变通，在2.X版本我们看见只要除数和被除数是整数的话，结果也必然是整数，这就造成了分子小于分母的正整数相除时得到的都是0，但是在3.X里面已经没有了这方面的问题。</p><p>不要小看这个除法，我之前写程序的时候在2.X这个版本上面浪费的心血都是泪，死活找不到原因，其实等你了解了才知道错误原因如此的简单。</p><p>我们讲到脚本的第一行添加  <code>#! usr/bin/python3</code>  这一句其实也有另外一个总用，白话说就是写上执行路径，让我们可以用./来执行程序，不单单用Python3命令来执行。</p><h3 id="输入函数input"><a href="#输入函数input" class="headerlink" title="输入函数input():"></a>输入函数input():</h3><p>raw_input函数被Python3废弃，统一使用input函数。这个区别很明显就是在2.X版本里面input另有作用。</p><p>注意：input()会将我们的输入统一改成字符串格式。如果我们在输入数字参与后续的运算时，要记得利用int()函数进行格式的转换。</p><h3 id="缩进："><a href="#缩进：" class="headerlink" title="缩进："></a>缩进：</h3><p>先说缩进：（tab键和space不可以混用）</p><p>Python3使用更加严格的缩进。Python2的缩进机制中，1个tab键和8个space是等价的，所以在缩进中可以同时允许tab和space在代码中共存。但是我们知道不同的IDE初始的缩进可能是不同的，这对于初学者来说可能根本找不到错误的原因。Python3中1个tab只能找另外一个tab替代，因此tab和space共存会导致报错：TabError: inconsistent use of tabs and spaces in indentation.</p><h3 id="import："><a href="#import：" class="headerlink" title="import："></a>import：</h3><p>import：（说是核心变化，但是目前用的不多）</p><p>Python2中相对路径的import会让我们没办法导入标准库。主要是在同一目录下面的话，若创建了和标准库同名的文件名将会导入失败。Python3中需要导入同一目录的文件必须使用绝对路径，否则只能使用相关导入的方式来进行导入。但是我们想想对文件的命名都是极力避开标准库名称。觉得和日常的相关性不大。</p><h3 id="数据类型："><a href="#数据类型：" class="headerlink" title="数据类型："></a>数据类型：</h3><p>之前在接触数据类型的时候由于一开始就学的3，所以那些淘汰的数据类型，也只是了解但是没有用过，简单的介绍一下。long整型被彻底废弃，统一改写成int类型代替。不等于只有“！=”，舍弃了“&lt;&gt;”。</p><h3 id="xrange："><a href="#xrange：" class="headerlink" title="xrange："></a>xrange：</h3><p>没了，xrange函数被Python3废弃，统一使用range，Python3中range的机制也进行修改并提高了大数据集生成效率，说白了就是涵盖了xrange的功能</p><h3 id="返回对象："><a href="#返回对象：" class="headerlink" title="返回对象："></a>返回对象：</h3><p>其实很多2版本的返回对象都是返回的列表，但是3版本中都返回了一个“容器”，可以使用迭代器取出，有的也可以直接list()强制转换（比如这些函数：dictionary关联的keys()、values()、items()，zip()，map()，filter()）。</p>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python3和Python2中int和long区别</title>
      <link href="cp/python/python23-long/"/>
      <url>cp/python/python23-long/</url>
      
        <content type="html"><![CDATA[<h3 id="LONG长整型"><a href="#LONG长整型" class="headerlink" title="LONG长整型"></a>LONG长整型</h3><p>python2有非浮点数准备的int和long类型。</p><p>int类型最大值不能超过sys.maxint，而且这个最大值是平台相关的。</p><p>可以通过在数字的末尾附上一个Ｌ来定义长整型，显然，它比int类型表示的数字范围更大。</p><p>在python3里，只有一种整数类型int,大多数情况下，和python２中的长整型类似。</p><table class="table table-hover table-striped" style="border-collapse:collapse;border-spacing:0px;color:rgb(62,63,58);font-family:Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:14px;"><thead><tr><th style="text-align:left;line-height:1.42857;vertical-align:bottom;border-top:0px;border-bottom:2px solid rgb(223,215,202);">python2</th><th style="text-align:left;line-height:1.42857;vertical-align:bottom;border-top:0px;border-bottom:2px solid rgb(223,215,202);">python3</th><th style="text-align:left;line-height:1.42857;vertical-align:bottom;border-top:0px;border-bottom:2px solid rgb(223,215,202);">备注</th></tr></thead><tbody><tr><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">x = 1000000000000L</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">x = 1000000000000</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">python2中的十进制长整型在python3中被替换为十进制普通整数</td></tr><tr><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">x = 0xFFFFFFFFFFFFL</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">x = 0xFFFFFFFFFFFF</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">python2里的十六进制长整型在python3里被替换为十六进制的普通整数</td></tr><tr><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">long(x)</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">int(x)</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">python3没有long()</td></tr><tr><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">type(x) is long</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">type(x) is int</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">python3用int判断是否为整型</td></tr><tr><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">isinstance(x, long)</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">isinstance(x, int)</td><td style="line-height:1.42857;vertical-align:top;border-top:1px solid rgb(223,215,202);">int检查整数类型</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>兄弟会_flask笔记01</title>
      <link href="python/flask/flask-note1/"/>
      <url>python/flask/flask-note1/</url>
      
        <content type="html"><![CDATA[<h1 id="课程介绍"><a href="#课程介绍" class="headerlink" title="课程介绍"></a>课程介绍</h1><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>我们用flask是写后台的</p><p>如果你看一个小程序很好看,你可以把他爬下来,或者通过技术的手段</p><p>工具,实现反编译</p><hr><p>举例:”网易严选” 网页端 pc端 app 甚至微信小程序</p><p>你的手机里面的程序都会产生文件,所以你才会越用越卡</p><p>node.js开发的一个工具,能反编译成一个差不多的东西</p><p>这个能快到什么程度呢,一个比较熟练的人,一天之内包括分编译,能把这个程序调试的差不多</p><p>比如这个:<a href="http://www.newdao.net/">牛刀云</a>包括<a href="https://shenyang.zbj.com/">猪八戒网</a>,都行</p><p>我们要做的就是使用flask做后台给小程序提供接口,小程序任意类型的都能做</p><h1 id="虚拟环境"><a href="#虚拟环境" class="headerlink" title="虚拟环境"></a>虚拟环境</h1><h3 id="在这之前我们需要学一个虚拟环境："><a href="#在这之前我们需要学一个虚拟环境：" class="headerlink" title="在这之前我们需要学一个虚拟环境："></a>在这之前我们需要学一个虚拟环境：</h3><p>VirtualEnv用于在一台机器上创建多个独立的Python虚拟运行环境，多个Python环境相互独立，互不影响，它能够：</p><ul><li>在没有权限的情况下安装新套件</li><li>不同应用可以使用不同的套件版本</li><li>套件升级不影响其他应用</li></ul><p>详情在这里:<a href="https://victorfengming.gitee.io/blog/python-venv/">Python中的虚拟环境-virtualenv</a></p><p>其实这个虚拟环境也有缺点,就是他只能用于python,我们可以在了解一个叫做<br>docker这个东东</p><p>docker就相当于硬件级的环境,这个可以快速的部署,它适合在大型的集群的上面才能显示他的优势</p><h3 id="在python3中还有一种方法"><a href="#在python3中还有一种方法" class="headerlink" title="在python3中还有一种方法"></a>在python3中还有一种方法</h3><p>安装python3的虚拟环境包</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install python3-venv</span><br></pre></td></tr></table></figure><p>创建虚拟环境</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 -m venv v1</span><br></pre></td></tr></table></figure><p>使用虚拟环境(激活)</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source v1/bin/activate</span><br></pre></td></tr></table></figure><p>导出虚拟环境记录文件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip freeze &gt; requirements.txt</span><br></pre></td></tr></table></figure><p>我又傻了,以后venv这个文件夹都不用往github上面推了</p><p>直接推一个<code>requirements.txt</code>文件就够了,小到没朋友</p><h1 id="Flask介绍"><a href="#Flask介绍" class="headerlink" title="Flask介绍"></a>Flask介绍</h1><p>Flask翻译,烧瓶,不是辣椒奥,这里要强调一下</p><p>犀牛角形状的水壶</p><hr><p>之所以选中Python（大蟒蛇的意思）作为该编程语言的名字，是取自英国20世纪70年代首播的电视喜剧《蒙提.派森干的飞行马戏团》（Monty Python’s Flying Circus）</p><p>吉多曾经参与过ABC语言的设计,不是说人家圣诞节真的没事儿才开发的python</p><p>不仅就你知道的C语言,还有A ,B语言,C++,C–,C#,这个ABC是一个语言</p><p>所以python开发参考了很多语言的特点,结合自己的经验</p><p>90年正式诞生第一个版本,2.7,和3.4两个比较大的版本</p><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>Flask是基于Werkzeug，Jinja 2和良好意图的基于Python的微框架</p><p>微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。</p><p>Flask 不会替你做出太多决策——比如使用何种数据库。</p><p>而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。</p><p>除此之外的一切都由可由你掌握。如此，Flask 可以与您珠联璧合</p><p>Flask 也许是“微小”的，但它已准备好在需求<strong>繁杂</strong>的生产环境中投入使用</p><hr><p>官网地址 Flask <a href="http://flask.pocoo.org/">http://flask.pocoo.org/</a></p><h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>第一个flask程序如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask</span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&#x27;/&#x27;</span></span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">hello_world</span>():</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&#x27;Hello World!&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app.run()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>简单吧!连上空格都算上,一共就不到10行代码,就能helloworld</p><h3 id="解析"><a href="#解析" class="headerlink" title="解析"></a>解析</h3><p><code>__name__</code>是一个魔术变量</p><p>一个工具:POSTMan</p><p>它能够默认任何请求方式</p><h3 id="Pymysql"><a href="#Pymysql" class="headerlink" title="Pymysql"></a>Pymysql</h3><p>这个玩意是python连接mysql数据库进行操作的工具api</p><h3 id="SQLAlchemy"><a href="#SQLAlchemy" class="headerlink" title="SQLAlchemy"></a>SQLAlchemy</h3><p>用于管理数据库的工具</p><p>这玩意能操作各种数据库,跟pymysql比起来更高一级</p><p>如果要连接mysql数据库,还是需要调pymysql的</p><p>它是python编程语言下的一款开源软件,提供了SQL工具包以及对象关系映射(ORM)工具</p><p>SQLAlchemy</p><h3 id="使用Flask-SQLAlchemy管理数据库"><a href="#使用Flask-SQLAlchemy管理数据库" class="headerlink" title="使用Flask-SQLAlchemy管理数据库"></a>使用Flask-SQLAlchemy管理数据库</h3><p>Flask-SQLAlchem这玩意是在flask框架中使用SQLAlchemy一个工具包,产品,它依赖SQLAlchemy</p><p>Flask-SQLAlchemy 是一个 Flask 扩展，简化了在 Flask 程序中使用 SQLAlchemy 的操作。</p><p>SQLAlchemy 是一个很强大的关系型数据库框架，支持多种数据库后台。</p><p>SQLAlchemy 提 供了高层 ORM，也提供了使用数据库原生 SQL 的低层功能</p><h3 id="模型操作-连接数据库"><a href="#模型操作-连接数据库" class="headerlink" title="模型操作(连接数据库)"></a>模型操作(连接数据库)</h3><p>在mysql数据库中创建一个数据库名为<code>myapp</code></p><p>创建一个python文件<code>models.py</code>内容如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask</span><br><span class="line"><span class="keyword">from</span> flask_sqlalchemy <span class="keyword">import</span> SQLAlchemy</span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line">app.config[<span class="string">&quot;SQLALCHEMY_DATABASE_URI&quot;</span>] = <span class="string">&quot;mysql+pymysql://root:@127.0.0.1:3306/myapp&quot;</span></span><br><span class="line"><span class="comment"># 如果设置成 True (默认情况)，Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。</span></span><br><span class="line">app.config[<span class="string">&quot;SQLALCHEMY_TRACK_MODIFICATIONS&quot;</span>] = <span class="literal">True</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 绑定app至SQLAlchemy</span></span><br><span class="line">db = SQLAlchemy(app)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#会员模型</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span>(<span class="params">db.Model</span>):</span></span><br><span class="line">    __tablename__ = <span class="string">&#x27;user&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">id</span> = db.Column(db.Integer,primary_key=<span class="literal">True</span>)</span><br><span class="line">    name = db.Column(db.String(<span class="number">100</span>),unique=<span class="literal">True</span>)</span><br><span class="line">    pwd= db.Column(db.String(<span class="number">100</span>))</span><br><span class="line">    email= db.Column(db.String(<span class="number">100</span>))</span><br><span class="line">    phone= db.Column(db.String(<span class="number">11</span>))</span><br><span class="line">    info= db.Column(db.Text)</span><br><span class="line">    face = db.Column(db.String(<span class="number">255</span>))</span><br><span class="line">    addtime = db.Column(db.DateTime,default=datetime.now)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># def __repr__(self):</span></span><br><span class="line">    <span class="comment"># return &#x27;&lt;User %r&gt;&#x27; % self.username</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    db.create_all()</span><br></pre></td></tr></table></figure><p>在第5行那里需要加上<code>+pymysql</code>,不然就报错,因为没有<code>mysqldb</code></p><p>但是你还不能装<code>mysqldb</code>,因为你装不上,都改名字了这个包</p><p>这里需要格外的注意,假装画一个重点符号</p><p>然后直接用python执行这个models.py脚本,你就会神奇的发现</p><p>你的<code>myapp</code>数据库中的多了一张表,里面字段都整好了,完美!</p><h3 id="数据库的增删改查"><a href="#数据库的增删改查" class="headerlink" title="数据库的增删改查"></a>数据库的增删改查</h3><p>在创建一个数据库,专门用来操作的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Stu</span>(<span class="params">db.Model</span>):</span></span><br><span class="line">    __tablename__ = <span class="string">&#x27;Stu&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">id</span> = db.Column(db.Integer,primary_key=<span class="literal">True</span>)</span><br><span class="line">    sname = db.Column(db.String(<span class="number">10</span>))</span><br><span class="line">    email = db.Column(db.String(<span class="number">50</span>))</span><br><span class="line">    age = db.Column(db.Integer)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    <span class="comment"># 创建数据表</span></span><br><span class="line">    db.create_all()</span><br></pre></td></tr></table></figure><h4 id="先手动在数据中整一条数据试试查询"><a href="#先手动在数据中整一条数据试试查询" class="headerlink" title="先手动在数据中整一条数据试试查询"></a>先手动在数据中整一条数据试试查询</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">查询数据</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line">res = User.query.<span class="built_in">all</span>()</span><br><span class="line">print(res)</span><br><span class="line">print(<span class="string">&#x27;-&#x27;</span>*<span class="number">80</span>)</span><br><span class="line">print(<span class="built_in">dir</span>(res[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;-&#x27;</span>*<span class="number">80</span>)</span><br><span class="line"><span class="comment"># print(type(res[0]).__dict__)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="增加"><a href="#增加" class="headerlink" title="增加"></a>增加</h4><p>向数据库插入数据分为三个步骤:</p><ul><li>创建 Python 对象</li><li>把它添加到会话</li><li>提交会话</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">数据的添加</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 1先创建一个模型对象</span></span><br><span class="line">s = Stu()</span><br><span class="line">s.sname = <span class="string">&#x27;战三&#x27;</span></span><br><span class="line">s.email = <span class="string">&#x27;zssag@163.com&#x27;</span></span><br><span class="line">s.age = <span class="number">18</span></span><br><span class="line"><span class="comment"># db 是之前的实例化的对象</span></span><br><span class="line"><span class="comment"># 这里的session不是session仅仅表示会话的意思</span></span><br><span class="line">db.session.add(s)</span><br><span class="line"><span class="comment"># 你要知道,这不是一个人开发的啊</span></span><br><span class="line"><span class="comment"># 那你学django的时候是那样用的,这回这样用,</span></span><br><span class="line"><span class="comment"># 那就这样了,用人家的东西就得挺着</span></span><br><span class="line"><span class="comment"># 那要完全都一样全写一个样,就用一个框架不就oK了么</span></span><br><span class="line"><span class="comment"># 这个要求是SQLAlchemy要求的,</span></span><br><span class="line"><span class="comment"># 这个时候还可以捕获异常,db.rollback还可以回滚,也就是说自带了事务处理了</span></span><br><span class="line">db.session.commit()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2数据添加.</span></span><br><span class="line"><span class="comment"># 这个数据实际上应该从表单中添加过来的,</span></span><br><span class="line"><span class="comment"># 所以我们假装构建一个这样的数据</span></span><br><span class="line">data = &#123;<span class="string">&#x27;sname&#x27;</span>:<span class="string">&#x27;lisi&#x27;</span>,<span class="string">&#x27;email&#x27;</span>:<span class="string">&#x27;lsasdfghafsgh@qq.com&#x27;</span>,<span class="string">&#x27;age&#x27;</span>:<span class="number">21</span>&#125;</span><br><span class="line"><span class="comment"># **拆参数,这个经常用,得理解</span></span><br><span class="line">s = Stu(**data)</span><br><span class="line">db.session.add(s)</span><br><span class="line">db.session.commit()</span><br></pre></td></tr></table></figure><h3 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h3><p>删除记录是十分类似的，使用 delete() 代替 add():</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">先获取对象</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line">ob = Stu.query.get(<span class="number">2</span>)</span><br><span class="line">db.session.delete(ob)</span><br><span class="line">db.session.commit()</span><br><span class="line">```    </span><br><span class="line"></span><br><span class="line"><span class="comment">### 修改</span></span><br><span class="line">    </span><br><span class="line">```python</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">先找到要改的</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line">ob = Stu.query.get(<span class="number">1</span>)</span><br><span class="line">ob.sname = <span class="string">&#x27;张三&#x27;</span></span><br><span class="line">db.session.add(ob)</span><br><span class="line">db.session.commit()</span><br><span class="line">```    </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">### 查询数据</span></span><br><span class="line">那么我们怎么从数据库中查询数据？为此，Flask-SQLAlchemy 在您的 Model 类上提供了 query 属性。</span><br><span class="line"></span><br><span class="line">当您访问它时，您会得到一个新的所有记录的查询对象。</span><br><span class="line"></span><br><span class="line">在使用 <span class="built_in">all</span>() 或者 first() 发起查询之前可以使用方法 <span class="built_in">filter</span>() 来过滤记录。</span><br><span class="line"></span><br><span class="line">如果您想要用主键查询的话，也可以使用 get()。</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line"></span><br><span class="line">下面的查询假设数据库中有如下条目:<span class="built_in">id</span></span><br><span class="line"></span><br><span class="line">&lt;table&gt;</span><br><span class="line">&lt;thead&gt;</span><br><span class="line">&lt;tr&gt;</span><br><span class="line">&lt;th style=&quot;text-align:left&quot;&gt;id&lt;/th&gt;</span><br><span class="line">&lt;th style=&quot;text-align:left&quot;&gt;username&lt;/th&gt;</span><br><span class="line">&lt;th style=&quot;text-align:left&quot;&gt;email&lt;/th&gt;</span><br><span class="line">&lt;/tr&gt;</span><br><span class="line">&lt;/thead&gt;</span><br><span class="line">&lt;tbody&gt;</span><br><span class="line">&lt;tr&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;1&lt;/td&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;admin&lt;/td&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;&lt;a href=&quot;mailto:admin%40example.com&quot; target=&quot;_blank&quot;&gt;admin@example.com&lt;/a&gt;&lt;/td&gt;</span><br><span class="line">&lt;/tr&gt;</span><br><span class="line">&lt;tr&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;2&lt;/td&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;peter&lt;/td&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;&lt;a href=&quot;mailto:peter%40example.org&quot; target=&quot;_blank&quot;&gt;peter@example.org&lt;/a&gt;&lt;/td&gt;</span><br><span class="line">&lt;/tr&gt;</span><br><span class="line">&lt;tr&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;3&lt;/td&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;guest&lt;/td&gt;</span><br><span class="line">&lt;td style=&quot;text-align:left&quot;&gt;&lt;a href=&quot;mailto:guest%40example.com&quot; target=&quot;_blank&quot;&gt;guest@example.com&lt;/a&gt;&lt;/td&gt;</span><br><span class="line">&lt;/tr&gt;</span><br><span class="line">&lt;/tbody&gt;</span><br><span class="line">&lt;/table&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#### 通过用户名查询用户:</span></span><br><span class="line">```shell</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>peter = User.query.filter_by(username=<span class="string">&#x27;peter&#x27;</span>).first()</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>peter.<span class="built_in">id</span></span><br><span class="line"><span class="number">1</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>peter.email</span><br><span class="line"><span class="string">u&#x27;peter@example.org&#x27;</span></span><br></pre></td></tr></table></figure><h4 id="同上但是查询一个不存在的用户名返回None"><a href="#同上但是查询一个不存在的用户名返回None" class="headerlink" title="同上但是查询一个不存在的用户名返回None:"></a>同上但是查询一个不存在的用户名返回None:</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;</span><span class="bash">&gt;&gt; missing = User.query.filter_by(username=<span class="string">&#x27;missing&#x27;</span>).first()</span></span><br><span class="line"><span class="meta">&gt;</span><span class="bash">&gt;&gt; missing is None</span></span><br><span class="line">True</span><br></pre></td></tr></table></figure><h4 id="使用更复杂的表达式查询一些用户"><a href="#使用更复杂的表达式查询一些用户" class="headerlink" title="使用更复杂的表达式查询一些用户:"></a>使用更复杂的表达式查询一些用户:</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;</span><span class="bash">&gt;&gt; User.query.filter(User.email.endswith(<span class="string">&#x27;@example.com&#x27;</span>)).all()</span></span><br><span class="line">[&lt;User u&#x27;admin&#x27;&gt;, &lt;User u&#x27;guest&#x27;&gt;]</span><br></pre></td></tr></table></figure><h4 id="按某种规则对用户排序"><a href="#按某种规则对用户排序" class="headerlink" title="按某种规则对用户排序:"></a>按某种规则对用户排序:</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;</span><span class="bash">&gt;&gt; User.query.order_by(User.username)</span></span><br><span class="line">[&lt;User u&#x27;admin&#x27;&gt;, &lt;User u&#x27;guest&#x27;&gt;, &lt;User u&#x27;peter&#x27;&gt;]</span><br></pre></td></tr></table></figure><h4 id="限制返回用户的数量"><a href="#限制返回用户的数量" class="headerlink" title="限制返回用户的数量:"></a>限制返回用户的数量:</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;</span><span class="bash">&gt;&gt; User.query.limit(1).all()</span></span><br><span class="line">[&lt;User u&#x27;admin&#x27;&gt;]</span><br></pre></td></tr></table></figure><h4 id="用主键查询用户"><a href="#用主键查询用户" class="headerlink" title="用主键查询用户:"></a>用主键查询用户:</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;</span><span class="bash">&gt;&gt; User.query.get(1)</span></span><br><span class="line">&lt;User u&#x27;admin&#x27;&gt;</span><br></pre></td></tr></table></figure><h3 id="在视图中查询"><a href="#在视图中查询" class="headerlink" title="在视图中查询"></a>在视图中查询</h3><p>当您编写 Flask 视图函数，对于不存在的条目返回一个 404 错误是非常方便的。因为这是一个很常见的问题，Flask-SQLAlchemy 为了解决这个问题提供了一个帮助函数。</p><hr><p>可以使用get_or_404()来代替get()，使用first_or_404()来代替first()。这样会抛出一个 404 错误，而不是返回None:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&#x27;/user/&lt;username&gt;&#x27;</span></span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">show_user</span>(<span class="params">username</span>):</span></span><br><span class="line">    user = User.query.filter_by(username=username).first_or_404()</span><br><span class="line">    <span class="keyword">return</span> render_template(<span class="string">&#x27;show_user.html&#x27;</span>, user=user)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> flask </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django笔记05-后台展示</title>
      <link href="python/Django/note/django-note5/"/>
      <url>python/Django/note/django-note5/</url>
      
        <content type="html"><![CDATA[<h1 id="后台商品数据展示"><a href="#后台商品数据展示" class="headerlink" title="后台商品数据展示"></a>后台商品数据展示</h1><h1 id="中间件"><a href="#中间件" class="headerlink" title="中间件"></a>中间件</h1><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>后台的权限,实际上只能是管理员能访问,而我们现在谁都能访问</p><p>这里我们需要做一个验证</p><p>这次我们先做一个模拟的,(假的),等前台都写完了,会有权限管理来用</p><p>这个不需要用过多的时间</p><p>如果要进行身份验证,我们做各种操作都需要验证</p><p>因此我们框架中有一个中间件</p><h3 id="中间件概念"><a href="#中间件概念" class="headerlink" title="中间件概念"></a>中间件概念</h3><p>中间件是一个轻量级、底层的插件系统，可以介入Django的请求和响应处理过程，修改Django的输入或输出<br>激活：添加到Django配置文件中的MIDDLEWARE_CLASSES元组中<br>使用中间件，可以干扰整个处理过程，每次请求中都会执行中间件的这个方法</p><h3 id="比如这样"><a href="#比如这样" class="headerlink" title="比如这样"></a>比如这样</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.http <span class="keyword">import</span> HttpResponse</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AdminLoginMiddleware</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, get_response</span>):</span></span><br><span class="line">        self.get_response = get_response</span><br><span class="line">        <span class="comment"># One-time configuration and initialization.</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__call__</span>(<span class="params">self, request</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 用户的请求路径# /myadmin/cate/index/</span></span><br><span class="line">        path = request.path</span><br><span class="line">        <span class="comment"># 定义允许访问的路径</span></span><br><span class="line">        arr = [<span class="string">&#x27;/myadmin/login/&#x27;</span>,<span class="string">&#x27;/myadmin/dologin/&#x27;</span>,<span class="string">&#x27;/myadmin/verifycode/&#x27;</span>]</span><br><span class="line">        <span class="comment"># 检测用户是否访问后台,并且不是进入登录页面</span></span><br><span class="line">        <span class="keyword">if</span> re.match(<span class="string">&#x27;/myadmin/&#x27;</span>,path) <span class="keyword">and</span> path <span class="keyword">not</span> <span class="keyword">in</span> arr:</span><br><span class="line">            <span class="comment"># 检测是否已经登录</span></span><br><span class="line">            AdminUser = request.session.get(<span class="string">&#x27;AdminUser&#x27;</span>,<span class="literal">None</span>)</span><br><span class="line">            <span class="keyword">if</span> <span class="keyword">not</span> AdminUser:</span><br><span class="line">                <span class="comment"># 没有登录</span></span><br><span class="line">                <span class="keyword">return</span> HttpResponse(<span class="string">&#x27;&lt;script&gt;alert(&quot;请先登录&quot;);location.href=&quot;/myadmin/login/&quot;&lt;/script&gt;&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        response = self.get_response(request)</span><br><span class="line">        <span class="keyword">return</span> response</span><br></pre></td></tr></table></figure><h3 id="验证码那点事儿"><a href="#验证码那点事儿" class="headerlink" title="验证码那点事儿"></a>验证码那点事儿</h3><p>静态资源如果重复访问,不会产生</p><p>所以验证码的刷新要在this.src后面加上?1</p><p>像这样:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;大括号开始 百分号 url &#x27;myadmin_verifycode&#x27; 百分号 大括号结束&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;&quot;</span> <span class="attr">style</span>=<span class="string">&quot;position:absolute; right: 2px; top: 5px&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;this.src = this.src+&#x27;?1&#x27;&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这样会越加越多,升级版本(用随机数字):</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;大括号开始 百分号 url &#x27;myadmin_vcode&#x27; 百分号大括号结束&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;this.src=&#x27;大括号开始百分号 url &#x27;myadmin_vcode&#x27; 百分号 大括号结束&#x27;+&#x27;?&#x27;+Math.random()&quot;</span> <span class="attr">style</span>=<span class="string">&quot;position: absolute;top:-5px;right: 2px;&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="前台页面的基本搭建"><a href="#前台页面的基本搭建" class="headerlink" title="前台页面的基本搭建"></a>前台页面的基本搭建</h3><p>后台是增删改查的流程</p><p>前台多数时候是查询</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django的MVT模式与MVC模式</title>
      <link href="python/Django/django-mvt/"/>
      <url>python/Django/django-mvt/</url>
      
        <content type="html"><![CDATA[<h1 id="Django的MVT模式与MVC模式"><a href="#Django的MVT模式与MVC模式" class="headerlink" title="Django的MVT模式与MVC模式"></a>Django的MVT模式与MVC模式</h1><p>在正式开始coding之前，我觉得有必要探讨下Django的MVT模式，理论和实践相结合，才能更好的掌握一门技术。</p><p>Django中的MVT模式，Django就是属于MVC模式。</p><p>MVC（Model-View-Controller）模型-视图-控制器，MVC是一种 软件框架模式，最开始用于Desktop程序开发，现在已被广泛使用，包括Web开发，MVT（Model-View- Template），Django内部的URLconf作为控制器的角色，负责了接收用户请求和转发请求的工作，Django 里更关注的是模型（Model）、模板(Template)和视图（Views），故称之为 Django MVT 模式。</p><h3 id="介绍MVT："><a href="#介绍MVT：" class="headerlink" title="介绍MVT："></a>介绍MVT：</h3><p>M全拼为Model，与MVC中的M功能相同，负责和数据库交互，进行数据处理。</p><p>V全拼为View，与MVC中的C功能相同，接收请求，进行业务处理，返回应答。</p><p>T全拼为Template，与MVC中的V功能相同，负责封装构造要返回的html。</p><p>Django中MVT的设计是遵守 MVC的流程去执行。</p><p>MVT即模型-模版-视图模式，其标准名称是有争议的。在MVC的解释中，视图描述了展现给用户的数据，是指所看到的数据，而不是如何看见它。在python中视图是指对某一特定URL的回调函数，因为回调函数描述了所要展现的数据。</p><p>模版用于将内容与展现分离。在django中，视图描述了要展现的数据，而视图一般转交给模版。模版描述了数据如何展现,控制器则是指django框架本身，通过URL配置，系统将一个请求发送到一个合适的视图。</p><h4 id="MVT执行顺序"><a href="#MVT执行顺序" class="headerlink" title="MVT执行顺序"></a>MVT执行顺序</h4><p>设计模式: 核心思想是分工,解耦,让不同的代码之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容</p><p>1,客户端发出请求,与关系型数据库进行交互</p><p>2,路由接收请求,根据请求地址查找视图</p><p>3,视图接收,处理 找到相应的Model(数据交互)</p><p>4, 与关系型数据库进行交互 取得数据  </p><p>5,将取到的数据返回给Model</p><p>6,将数据交给view进行处理</p><p>7,将数据套入到需要的template,封装相对应的html,css,js编写的模板语言</p><p>8,将封装好的模板语言返回给view进行处理</p><p>9,客户端接受结果进行渲染html和css 执行js</p><p>MVT基于MVC，所以流程与MVC十分相似，客户端发送请求，根据请求地址去寻找视图，视图把接收并处理请求，访问数据库，提取数据，由视图返回结果到模板上，客户端接收渲染</p><p>MVT的处理过程： Django框架接收了用户请求和参数后，通过正则表达式匹配URL，发送到对应视图进行处理,处理完毕后，视图调用M处理数据，再调用T返回界面给浏览器,然后显示到页面上。</p><h3 id="介绍MVC："><a href="#介绍MVC：" class="headerlink" title="介绍MVC："></a>介绍MVC：</h3><p>M全拼为Model（模块），主要封装对数据库层的访问， 数据处理，对数据库中的数据进行增、删、改、查操作。</p><p>V全拼为View（视图），界面显示，用于封装结果，生成页面展示的html内容。</p><p>C全拼为Controller（控制器），逻辑处理，用于接收请求，处理业务逻辑，与Model和View交互，返回结果。</p><p>MVC模块的核心宗旨就是：解耦，模型的复用，让不同的代码之间的耦合度降低，增强代码的扩展性和可移植性还有方便维护，模型不用关心处理结果展现，比如模型返回一些数据，然后交给不用的视图展现，可以使用不同的视图来访问同一个模型。方便测试， 比如，将业务逻辑代码写在servlet里面，需要部署到容器上，然后才能测试。而将业务逻辑代码写在类里面，可以直接用main()测试（不依赖容器）。</p><p>MVC即模型，里面存在视图与控制器模式，就是为那些需要为同样的数据提供多个视图的应用程序而设计的。它很好地实现了数据层与表示层的分离，特别适用于开发与用户图形界面有关的应用程序，能够提高效率，降低耦合度，增加代码的可移植性，可以更好的去维护代码。</p><p>控制器：控制器是用来处理用户命令以及程序事件，模型维护数据并提供数据访问方法；</p><p>视图：视图用于数据的显示，把数据库中的数据显示到页面上。</p><h4 id="MVC流程"><a href="#MVC流程" class="headerlink" title="MVC流程"></a>MVC流程</h4><p>MVC设计模式也可以叫做MVC的流程，从开头到结束，是怎样一步步执行的：</p><p>1,客户端发出请求</p><p>2,controll,接收请求,进行业务处理 发送给Model</p><p>3, 与关系型数据库进行交互 取得数据  </p><p>4,将取到的数据返回给Model</p><p>5,将数据交给controller.进行处理</p><p>6,将数据给view进行HTML,css,js等进行封装</p><p>7,返回封装好的HTML给controll</p><p>8,controll返回给客户端进行渲染HTML和css执行js</p><h4 id="MVC的缺点：事物都有两面性，有好有坏，MVC也是这样，他的缺点如下"><a href="#MVC的缺点：事物都有两面性，有好有坏，MVC也是这样，他的缺点如下" class="headerlink" title="MVC的缺点：事物都有两面性，有好有坏，MVC也是这样，他的缺点如下"></a>MVC的缺点：事物都有两面性，有好有坏，MVC也是这样，他的缺点如下</h4><p>使用mvc，会增加代码量、相应地也会增加软件开发的成文，设计的难度也会增加,适合大型项目。</p><p>（1）视图跟控制器过于紧密的连接，（视图与控制器是相互分离，但却是联系紧密的部件，视图没有控制器的存在，其应用是很有限的，反之亦然，这样就妨碍了他们的独立重用。【例如，不可能总是在jsp页面中直接访问模型，一般放在逻辑控制层进行处理，servlet】）</p><p>（2）增加了系统结构和实现的复杂性</p><p>（3）部分高级界面工具或构造器不支持MVC</p><p>（4）视图对模型数据的访问效率低（依据模型操作接口的不同，视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问，也将损害操作性能。【例如，页面的有一部分数据我并没有更新，但是提交到模型层照样会去获得返回显示 】）</p><p>（5）调试应用程序带来了一定的困难。每个构件在使用之前都需要经过彻底的测试。</p><p>简单的小型项目，使用MVC设计反而会降低开发效率，层和层虽然相互分离，但是之间关联性太强，没有做到独立的重用</p><h3 id="总结："><a href="#总结：" class="headerlink" title="总结："></a>总结：</h3><p>Django的MVT模式本质上和MVC是一样的，也是为了各组件间保持松耦合关系，只是定义上有些许不同，流程也是大致一样，本质上相同，两者的MV都是相同的，不同的是：T代表了模板，C代表了控制器，Django遵循的是MVC模式，而MVT是Django中的一种回调函数。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>pycharm中运行django的相关配置</title>
      <link href="python/Django/pycharm-config-django/"/>
      <url>python/Django/pycharm-config-django/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>小编在使用pycharm写django项目的时候遇到一个问题:</p><p>在cmd中能够正常运行django程序,<br>pycharm 中运行不了django的程序，看错误是：</p><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">django.core.exceptions.ImproperlyConfigured: </span><br><span class="line">Requested setting CACHES, but settings are not configured. </span><br><span class="line">You must either define the environment variable </span><br><span class="line">DJANGO_SETTINGS_MODULE or call settings.</span><br><span class="line">configure() before accessing settings. </span><br></pre></td></tr></table></figure><p>结果百度了半天没结果，最后还是在 老外的网站上找到了答案:</p><h3 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h3><p>本来django项目在 python shell 中可以完美运行，在pycharm里面就不行，原因是pycharm 要你配置一个  环境变量  <code>DJANGO_SETTINGS_MODULE</code> 这个变量告诉django项目去找哪一个<code>settings</code> 文件。  </p><h3 id="具体的步骤："><a href="#具体的步骤：" class="headerlink" title="具体的步骤："></a>具体的步骤：</h3><p>1、Run  –&gt;  EditConfigures </p><p>2、找到python一项  具体名字是 Python tests（注意不是django那一个），然后修改里面的Environment variables 添加一项。名称是<code>DJANGO_SETTINGS_MODULE</code>  值是  你的settings,比如 <code>mysite.settings</code> 。</p><p>本文转自:<a href="https://www.cnblogs.com/lout/articles/4149591.html">https://www.cnblogs.com/lout/articles/4149591.html</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django笔记04-项目搭建</title>
      <link href="python/Django/note/django-note4/"/>
      <url>python/Django/note/django-note4/</url>
      
        <content type="html"><![CDATA[<h1 id="项目开发流程"><a href="#项目开发流程" class="headerlink" title="项目开发流程"></a>项目开发流程</h1><ul><li>需求开发<br>《用户需求说明书》<br>《软件需求规格说明书》</li><li>技术预研<br>《技术预研计划》<br>《技术预研报告》</li><li>系统设计<br>《体系结构设计报告》<br>《用户界面报告》<br>《数据库设计报告》<br>《模块设计报告》</li><li>实现与测试<br>《实现与测试计划》<br>《编程文档》</li><li>系统测试<br>《系统测试计划》<br>《测试用例》<br>《测试报告》</li><li>Beta 测试<br>《Beta 测试协议》<br>《Beta 测试报告》</li><li>客户验收 《客户验收计划》<br>《客户验收报告》</li><li>技术评审<br>《技术评审计划》<br>《技术评审报告》<br>《技术评审检查表》<h1 id="项目搭建"><a href="#项目搭建" class="headerlink" title="项目搭建"></a>项目搭建</h1></li></ul><h1 id="后台之会员编辑"><a href="#后台之会员编辑" class="headerlink" title="后台之会员编辑"></a>后台之会员编辑</h1><h3 id="地址的使用"><a href="#地址的使用" class="headerlink" title="地址的使用"></a>地址的使用</h3><p>在项目中头像上传时,使用的地址</p><ul><li>为什么有些地方写 <code>/static/uploads/</code></li><li>有些地方写 <code>./static/uploads/</code></li><li>甚至<code>/home/yc/py16/py16-project/web/static/uploads/</code></li></ul><p>总结来说:两种情况</p><ul><li><p>一种是系统操作(os模块),可以使用<code>./static/uploads/</code>或者 <code>/home/yc/py16/py16-project/web/static/uploads/</code></p></li><li><p>第二种是给服务器使用,浏览器访问时使用 <code>/static/uploads/</code>,因为此处<code>/</code>代表当前服务器地址(<code>http://127.0.0.1:8000/</code>)</p></li></ul><p><code>127.0.0.1</code><br><code>localhost</code></p><p><code>location.href = /index</code>这个使用的也是当前服务器地址</p><h3 id="分页优化解决方案"><a href="#分页优化解决方案" class="headerlink" title="分页优化解决方案"></a>分页优化解决方案</h3><p>自定义模板标签</p><h3 id="5-URL的反向解析"><a href="#5-URL的反向解析" class="headerlink" title="5. URL的反向解析"></a>5. URL的反向解析</h3><p>如果在视图、模板中使用硬编码的链接，在urlconf发生改变时，维护是一件非常麻烦的事情</p><ul><li>解决：在做链接时，通过指向urlconf的名称，动态生成链接地址</li><li>视图：使用django.core.urlresolvers.reverse()函数</li><li>模板：使用url模板标签</li></ul><h3 id="js中的知识点补充"><a href="#js中的知识点补充" class="headerlink" title="js中的知识点补充"></a>js中的知识点补充</h3><p><code>$(this)</code><br>是一个伪变量,在不同的作用域里表示的不同</p><p>比如这样:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 删除</span></span><br><span class="line">    $(<span class="string">&#x27;.removeCate&#x27;</span>).click(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="comment">// 获取当前选择的分类的id</span></span><br><span class="line">        <span class="keyword">var</span> cid = $(<span class="built_in">this</span>).attr(<span class="string">&#x27;cid&#x27;</span>)</span><br><span class="line">        <span class="keyword">var</span> a = $(<span class="built_in">this</span>)</span><br><span class="line">        <span class="comment">// 发送ajax请求.到后台执行删除</span></span><br><span class="line">        $.get(<span class="string">&#x27;url&#x27;</span>,&#123;<span class="string">&#x27;cid&#x27;</span>:cid&#125;,<span class="function"><span class="keyword">function</span>(<span class="params">data</span>)</span>&#123;</span><br><span class="line">            <span class="comment">// 判断当前的返回值</span></span><br><span class="line">            <span class="keyword">if</span>(data[<span class="string">&#x27;code&#x27;</span>] == <span class="number">0</span>)&#123;</span><br><span class="line">                <span class="comment">// 删除成功</span></span><br><span class="line">                <span class="comment">// $(this).parents(&#x27;tr&#x27;).remove()</span></span><br><span class="line">                <span class="comment">//  此处的 $(this) 是谁? ajax对象 XMLHttpRequest</span></span><br><span class="line">                a.parents(<span class="string">&#x27;tr&#x27;</span>).remove()</span><br><span class="line">            &#125;</span><br><span class="line">            alert(data[<span class="string">&#x27;msg&#x27;</span>])</span><br><span class="line">        &#125;,<span class="string">&#x27;json&#x27;</span>)</span><br><span class="line">        </span><br><span class="line"></span><br><span class="line">    &#125;)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python脚本实现汉字转拼音</title>
      <link href="python/collection/python-pinyin/"/>
      <url>python/collection/python-pinyin/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>中华文化博大精深，是中华民族的财富，吸收和继承发扬中 华文化，是现代每个炎黄子孙无可推卸的天职。</p><p>今天小编就交大家用python写一个脚本,实现汉子和拼音之间的转换</p><h3 id="pinyin-py"><a href="#pinyin-py" class="headerlink" title="pinyin.py"></a>pinyin.py</h3><p>汉字转拼音,With Python</p><p>Example:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pinyin <span class="keyword">import</span> PinYin</span><br><span class="line"></span><br><span class="line">test = PinYin()</span><br><span class="line">test.load_word()</span><br><span class="line">test.hanzi2pinyin(string=<span class="string">&#x27;钓鱼岛是中国的&#x27;</span>)</span><br></pre></td></tr></table></figure><p>Out:</p><pre><code>test.hanzi2pinyin(string=&#39;钓鱼岛是中国的&#39;)[&#39;diao&#39;, &#39;yu&#39;, &#39;dao&#39;, &#39;shi&#39;, &#39;zhong&#39;, &#39;guo&#39;, &#39;de&#39;]    test.hanzi2pinyin_split(string=&#39;钓鱼岛是中国的&#39;, split=&quot;-&quot;)diao-yu-dao-shi-zhong-guo-de</code></pre><h3 id="主程序"><a href="#主程序" class="headerlink" title="主程序"></a>主程序</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">    Author:cleverdeng</span></span><br><span class="line"><span class="string">    E-mail:clverdeng@gmail.com</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"></span><br><span class="line">__version__ = <span class="string">&#x27;0.9&#x27;</span></span><br><span class="line">__all__ = [<span class="string">&quot;PinYin&quot;</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> os.path</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">PinYin</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, dict_file=<span class="string">&#x27;word.data&#x27;</span></span>):</span></span><br><span class="line">        self.word_dict = &#123;&#125;</span><br><span class="line">        self.dict_file = dict_file</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">load_word</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> os.path.exists(self.dict_file):</span><br><span class="line">            <span class="keyword">raise</span> IOError(<span class="string">&quot;NotFoundFile&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(self.dict_file) <span class="keyword">as</span> f_obj:</span><br><span class="line">            <span class="keyword">for</span> f_line <span class="keyword">in</span> f_obj.readlines():</span><br><span class="line">                <span class="keyword">try</span>:</span><br><span class="line">                    line = f_line.split(<span class="string">&#x27;    &#x27;</span>)</span><br><span class="line">                    self.word_dict[line[<span class="number">0</span>]] = line[<span class="number">1</span>]</span><br><span class="line">                <span class="keyword">except</span>:</span><br><span class="line">                    line = f_line.split(<span class="string">&#x27;   &#x27;</span>)</span><br><span class="line">                    self.word_dict[line[<span class="number">0</span>]] = line[<span class="number">1</span>]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">hanzi2pinyin</span>(<span class="params">self, string=<span class="string">&quot;&quot;</span></span>):</span></span><br><span class="line">        result = []</span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> <span class="built_in">isinstance</span>(string, <span class="built_in">str</span>):</span><br><span class="line">            string = string.decode(<span class="string">&quot;utf-8&quot;</span>)</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> char <span class="keyword">in</span> string:</span><br><span class="line">            key = <span class="string">&#x27;%X&#x27;</span> % <span class="built_in">ord</span>(char)</span><br><span class="line">            result.append(self.word_dict.get(key, char).split()[<span class="number">0</span>][:-<span class="number">1</span>].lower())</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> result</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">hanzi2pinyin_split</span>(<span class="params">self, string=<span class="string">&quot;&quot;</span>, split=<span class="string">&quot;&quot;</span></span>):</span></span><br><span class="line">        result = self.hanzi2pinyin(string=string)</span><br><span class="line">        <span class="keyword">if</span> split == <span class="string">&quot;&quot;</span>:</span><br><span class="line">            <span class="keyword">return</span> result</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> split.join(result)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    test = PinYin()</span><br><span class="line">    test.load_word()</span><br><span class="line">    string = <span class="string">&quot;钓鱼岛是中国的&quot;</span></span><br><span class="line">    print(<span class="string">&quot;in: %s&quot;</span> % string)</span><br><span class="line">    print(<span class="string">&quot;out: %s&quot;</span> % <span class="built_in">str</span>(test.hanzi2pinyin(string=string)))</span><br><span class="line">    print(<span class="string">&quot;out: %s&quot;</span> % test.hanzi2pinyin_split(string=string, split=<span class="string">&quot;-&quot;</span>))</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="字典"><a href="#字典" class="headerlink" title="字典"></a>字典</h3><p>这里我们需要一个转换库</p><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">3400    QIU1</span><br><span class="line">3401    TIAN3 TIAN4</span><br><span class="line">3404    KUA4</span><br><span class="line">3405    WU3</span><br><span class="line">3406    YIN3</span><br><span class="line">340C    SI4 YI2</span><br><span class="line">3416    YE4</span><br><span class="line">341C    CHOU2</span><br><span class="line">3421    NUO4</span><br><span class="line">3424    QIU2</span><br><span class="line">3428    XU4</span><br><span class="line">3429    XING2</span><br><span class="line">342B    XIONG1</span><br><span class="line">342C    LIU2</span><br><span class="line">342D    LIN3</span><br><span class="line">342E    XIANG1</span><br><span class="line">342F    YONG1</span><br><span class="line">3430    XIN4</span><br><span class="line">3431    ZHEN3</span><br><span class="line">3432    DAI4</span><br><span class="line">3433    WU4</span><br><span class="line">3434    PAN1</span><br><span class="line">3437    MA3 MA4 MIAN2</span><br></pre></td></tr></table></figure><h3 id="转载说明"><a href="#转载说明" class="headerlink" title="转载说明"></a>转载说明</h3><p>CSDN:<a href="https://blog.csdn.net/u011389474/article/details/60144194">https://blog.csdn.net/u011389474/article/details/60144194</a>　　　</p><p>作者:cleverdeng</p><p>项目地址: <a href="https://github.com/cleverdeng/pinyin.py">https://github.com/cleverdeng/pinyin.py</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python脚本实现图片加水印</title>
      <link href="python/collection/python-shuiyin/"/>
      <url>python/collection/python-shuiyin/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>图片是指由图形、图像等构成的平面媒体,有形式的事物，我们看到的，是图画、照片、拓片等的统称。</p><p>为了保护一些原创图片的版权,某些时候我们需要在图片上面,加上水印,当然你可以用Photoshop来做,只不过如果图片数量过多,亦或者图片的动态生成的时候,使用ps将会稍有吃力.</p><p>今天小编就交大家用python写一个脚本,实现图片加水印</p><h3 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h3><p>python3.7 环境:<a href="https://victorfengming.gitee.io/python/install/python-install-window/">python安装以及版本检测</a></p><p>pycharm2019:<a href="https://victorfengming.gitee.io/ide/jetbrains/pycharm/pycharm-install/">PyCharm的安装以及破解</a></p><p>pillow库的安装</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install pillow</span><br></pre></td></tr></table></figure><p>关于pip的安装,可以参考:<a href="https://victorfengming.gitee.io/python/install/python-install-pip/">Python pip 安装与使用</a><br>和<a href="https://victorfengming.gitee.io/python/collection/pip-conf/">pip配置</a></p><h3 id="直接就上代码"><a href="#直接就上代码" class="headerlink" title="直接就上代码"></a>直接就上代码</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by 秋叶夏风</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;图片加水印&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入所需要的库</span></span><br><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image, ImageDraw, ImageFont</span><br><span class="line"></span><br><span class="line">im = Image.<span class="built_in">open</span>(<span class="string">&quot;6.jpg&quot;</span>).convert(<span class="string">&#x27;RGBA&#x27;</span>)</span><br><span class="line"><span class="comment"># 6.jpg的需要加图片的地址</span></span><br><span class="line">txt = Image.new(<span class="string">&#x27;RGBA&#x27;</span>, im.size, (<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>))</span><br><span class="line"><span class="comment"># 定义字体对象</span></span><br><span class="line">fnt = ImageFont.truetype(<span class="string">&quot;c:/Windows/fonts/Tahoma.ttf&quot;</span>, <span class="number">20</span>)</span><br><span class="line">d = ImageDraw.Draw(txt)</span><br><span class="line"><span class="comment"># 设置水印内容,字体</span></span><br><span class="line">d.text((txt.size[<span class="number">0</span>] - <span class="number">80</span>, txt.size[<span class="number">1</span>] - <span class="number">30</span>), <span class="string">&quot;shuiyin&quot;</span>, font=fnt, fill=(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>))</span><br><span class="line">out = Image.alpha_composite(im, txt)</span><br><span class="line"><span class="comment"># 显示图片</span></span><br><span class="line">out.show()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django笔记03-模板引擎</title>
      <link href="python/Django/note/django-note3/"/>
      <url>python/Django/note/django-note3/</url>
      
        <content type="html"><![CDATA[<h1 id="CSRF攻击"><a href="#CSRF攻击" class="headerlink" title="CSRF攻击"></a>CSRF攻击</h1><p>CSRF（Cross-site request forgery）跨站请求伪造，也被称为“One Click Attack”或者Session Riding，通常缩写为CSRF或者XSRF，是一种对网站的恶意利用。尽管听起来像跨站脚本XSS，但它与XSS非常不同，XSS利用站点内的信任用户，而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比，CSRF攻击往往不大流行（因此对其进行防范的资源也相当稀少）和难以防范，所以被认为比XSS更具危险性</p><p>CSRF中间件和模板标签为防止跨站点请求伪造提供了易用的保护。</p><p>当恶意网站包含链接，表单按钮或某些旨在在您的网站上执行某些操作的JavaScript时，会使用在浏览器中访问恶意网站的登录用户的凭据进行此类攻击。</p><p>还介绍了一种相关攻击类型，即“登录CSRF”，攻击网站欺骗用户的浏览器，以便使用其他人的凭证登录到网站。</p><h1 id="Template模板"><a href="#Template模板" class="headerlink" title="Template模板"></a>Template模板</h1><h3 id="模板概念"><a href="#模板概念" class="headerlink" title="模板概念"></a>模板概念</h3><p>作为Web 框架，Django 需要一种很便利的方法以动态地生成HTML。最常见的做法是使用模板。</p><p>模板包含所需HTML 输出的静态部分，以及一些特殊的语法，描述如何将动态内容插入。</p><h3 id="模板语法"><a href="#模板语法" class="headerlink" title="模板语法"></a>模板语法</h3><h4 id="1-变量"><a href="#1-变量" class="headerlink" title="1.变量"></a>1.变量</h4><ul><li><p>变量输出语法<code>&#123;&#123; var &#125;&#125;</code></p></li><li><p>当模版引擎遇到一个变量，将计算这个变量，然后将结果输出</p></li><li><p>变量名必须由字母、数字、下划线（不能以下划线开头）和点组成</p></li><li><p>当模版引擎遇到点(“.”)，会按照下列顺序查询：</p><ul><li>字典查询，例如：foo[“bar”]</li><li>属性或方法查询，例如：foo.bar</li><li>数字索引查询，例如：foo[bar]</li></ul></li><li><p>如果变量不存在， 模版系统将插入’’ (空字符串)</p></li><li><p>在模板中调用方法时不能传递参数</p></li></ul><h4 id="2-标签"><a href="#2-标签" class="headerlink" title="2.标签"></a>2.标签</h4><ul><li>语法<code>&#123; %  tag  % &#125;</code></li><li>作用<ul><li>在输出中创建文本</li><li>控制循环或逻辑</li><li>加载外部信息到模板中<h5 id="for标签"><a href="#for标签" class="headerlink" title="for标签"></a>for标签</h5><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123; %  for ... in ...  % &#125;</span><br><span class="line">    循环逻辑</span><br><span class="line">&#123; %  endfor  % &#125;</span><br></pre></td></tr></table></figure><h5 id="if标签"><a href="#if标签" class="headerlink" title="if标签"></a>if标签</h5><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123; %  if ...  % &#125;</span><br><span class="line">    逻辑1</span><br><span class="line">&#123; %  elif ...  % &#125;</span><br><span class="line">    逻辑2</span><br><span class="line">&#123; %  else  % &#125;</span><br><span class="line">    逻辑3</span><br><span class="line">&#123; %  endif  % &#125;</span><br></pre></td></tr></table></figure><h5 id="comment标签"><a href="#comment标签" class="headerlink" title="comment标签"></a>comment标签</h5><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123; %  comment  % &#125;</span><br><span class="line">    多行注释</span><br><span class="line">&#123; %  endcomment  % &#125;</span><br></pre></td></tr></table></figure><h5 id="include：加载模板并以标签内的参数渲染"><a href="#include：加载模板并以标签内的参数渲染" class="headerlink" title="include：加载模板并以标签内的参数渲染"></a>include：加载模板并以标签内的参数渲染</h5><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123; %  include &quot;base/index.html&quot;  % &#125;</span><br></pre></td></tr></table></figure><h5 id="url：反向解析"><a href="#url：反向解析" class="headerlink" title="url：反向解析"></a>url：反向解析</h5><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123; %  url &#x27;name&#x27; p1 p2  % &#125;</span><br></pre></td></tr></table></figure><h5 id="csrf-token：这个标签用于跨站请求伪造保护"><a href="#csrf-token：这个标签用于跨站请求伪造保护" class="headerlink" title="csrf_token：这个标签用于跨站请求伪造保护"></a>csrf_token：这个标签用于跨站请求伪造保护</h5><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123; %  csrf_token  % &#125;</span><br></pre></td></tr></table></figure></li></ul></li></ul><h3 id="Django框架自带的后台"><a href="#Django框架自带的后台" class="headerlink" title="Django框架自带的后台"></a>Django框架自带的后台</h3><ol><li><p>在浏览器访问 admin<br><code>http://127.0.0.1:8000/admin/</code></p></li><li><p>需要登录,因此要创建一个超级用户<br>在命令行执行下一个命令进行创建<br><code>python3 manage.py createsuperuser</code></p></li><li><p>重新启动服务后 ,使用创建的用户进行后台的登录</p></li><li><p>配置settings.py文件,配置语言和时区</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">LANGUAGE_CODE = <span class="string">&#x27;zh-Hans&#x27;</span></span><br><span class="line">TIME_ZONE = <span class="string">&#x27;Asia/Shanghai&#x27;</span></span><br><span class="line">USE_I18N = <span class="literal">True</span></span><br><span class="line">USE_L10N = <span class="literal">True</span></span><br><span class="line">USE_TZ = <span class="literal">False</span></span><br></pre></td></tr></table></figure><h1 id="自定义过滤-器"><a href="#自定义过滤-器" class="headerlink" title="自定义过滤/器"></a>自定义过滤/器</h1></li><li><p>在应用中创建一个templatetags文件夹</p></li><li><p>在templatetags 包中定义一个模块文件diytags.py</p></li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> django <span class="keyword">import</span> template</span><br><span class="line"></span><br><span class="line">register = template.Library()</span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27; 自定义过滤器&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="meta">@register.filter</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">yc_upper</span>(<span class="params">val</span>):</span></span><br><span class="line">    <span class="keyword">return</span> val.upper()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27; 自定义标签&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">from</span> django.utils.html <span class="keyword">import</span> format_html</span><br><span class="line"><span class="meta">@register.simple_tag</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">jia</span>(<span class="params">a,b</span>):</span></span><br><span class="line">    res = <span class="built_in">int</span>(a) + <span class="built_in">int</span>(b)</span><br><span class="line">    <span class="keyword">return</span> res</span><br><span class="line"></span><br></pre></td></tr></table></figure><ol start="3"><li>在需要使用的模板中, 导入自定义的模块</li></ol><h1 id="验证码"><a href="#验证码" class="headerlink" title="验证码"></a>验证码</h1><p>这里调用的PIL库实现的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.http <span class="keyword">import</span> HttpResponse</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">verifycode</span>(<span class="params">request</span>):</span></span><br><span class="line">    <span class="comment">#引入绘图模块</span></span><br><span class="line">    <span class="keyword">from</span> PIL <span class="keyword">import</span> Image, ImageDraw, ImageFont</span><br><span class="line">    <span class="comment">#引入随机函数模块</span></span><br><span class="line">    <span class="keyword">import</span> random</span><br><span class="line">    <span class="comment">#定义变量，用于画面的背景色、宽、高</span></span><br><span class="line">    bgcolor = (random.randrange(<span class="number">20</span>, <span class="number">100</span>), random.randrange(</span><br><span class="line">        <span class="number">20</span>, <span class="number">100</span>), <span class="number">255</span>)</span><br><span class="line">    width = <span class="number">100</span></span><br><span class="line">    height = <span class="number">25</span></span><br><span class="line">    <span class="comment">#创建画面对象</span></span><br><span class="line">    im = Image.new(<span class="string">&#x27;RGB&#x27;</span>, (width, height), bgcolor)</span><br><span class="line">    <span class="comment">#创建画笔对象</span></span><br><span class="line">    draw = ImageDraw.Draw(im)</span><br><span class="line">    <span class="comment">#调用画笔的point()函数绘制噪点</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="number">100</span>):</span><br><span class="line">        xy = (random.randrange(<span class="number">0</span>, width), random.randrange(<span class="number">0</span>, height))</span><br><span class="line">        fill = (random.randrange(<span class="number">0</span>, <span class="number">255</span>), <span class="number">255</span>, random.randrange(<span class="number">0</span>, <span class="number">255</span>))</span><br><span class="line">        draw.point(xy, fill=fill)</span><br><span class="line">    <span class="comment">#定义验证码的备选值</span></span><br><span class="line">    str1 = <span class="string">&#x27;ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0&#x27;</span></span><br><span class="line">    <span class="comment">#随机选取4个值作为验证码</span></span><br><span class="line">    rand_str = <span class="string">&#x27;&#x27;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="number">4</span>):</span><br><span class="line">        rand_str += str1[random.randrange(<span class="number">0</span>, <span class="built_in">len</span>(str1))]</span><br><span class="line">    <span class="comment">#构造字体对象</span></span><br><span class="line">    font = ImageFont.truetype(<span class="string">&#x27;FreeMono.ttf&#x27;</span>, <span class="number">23</span>)</span><br><span class="line">    <span class="comment">#构造字体颜色</span></span><br><span class="line">    fontcolor = (<span class="number">255</span>, random.randrange(<span class="number">0</span>, <span class="number">255</span>), random.randrange(<span class="number">0</span>, <span class="number">255</span>))</span><br><span class="line">    <span class="comment">#绘制4个字</span></span><br><span class="line">    draw.text((<span class="number">5</span>, <span class="number">2</span>), rand_str[<span class="number">0</span>], font=font, fill=fontcolor)</span><br><span class="line">    draw.text((<span class="number">25</span>, <span class="number">2</span>), rand_str[<span class="number">1</span>], font=font, fill=fontcolor)</span><br><span class="line">    draw.text((<span class="number">50</span>, <span class="number">2</span>), rand_str[<span class="number">2</span>], font=font, fill=fontcolor)</span><br><span class="line">    draw.text((<span class="number">75</span>, <span class="number">2</span>), rand_str[<span class="number">3</span>], font=font, fill=fontcolor)</span><br><span class="line">    <span class="comment">#释放画笔</span></span><br><span class="line">    <span class="keyword">del</span> draw</span><br><span class="line">    <span class="comment">#存入session，用于做进一步验证</span></span><br><span class="line">    request.session[<span class="string">&#x27;verifycode&#x27;</span>] = rand_str</span><br><span class="line">    <span class="comment">#内存文件操作</span></span><br><span class="line">    <span class="keyword">import</span> cStringIO</span><br><span class="line">    buf = cStringIO.StringIO()</span><br><span class="line">    <span class="comment">#将图片保存在内存中，文件类型为png</span></span><br><span class="line">    im.save(buf, <span class="string">&#x27;png&#x27;</span>)</span><br><span class="line">    <span class="comment">#将内存中的图片数据返回给客户端，MIME类型为图片png</span></span><br><span class="line">    <span class="keyword">return</span> HttpResponse(buf.getvalue(), <span class="string">&#x27;image/png&#x27;</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="ajax实现城市多级联动"><a href="#ajax实现城市多级联动" class="headerlink" title="ajax实现城市多级联动"></a>ajax实现城市多级联动</h1><h4 id="视图函数"><a href="#视图函数" class="headerlink" title="视图函数"></a>视图函数</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">citys</span>(<span class="params">request</span>):</span></span><br><span class="line">    <span class="comment"># 从数据库中获取所有的一级城市信息</span></span><br><span class="line">    data = Citys.objects.<span class="built_in">filter</span>(upid=<span class="number">0</span>)</span><br><span class="line">    <span class="comment"># 分配数据</span></span><br><span class="line">    content = &#123;<span class="string">&#x27;data&#x27;</span>:data&#125;</span><br><span class="line">    <span class="keyword">return</span> render(request,<span class="string">&#x27;citys.html&#x27;</span>,content)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="urls路由"><a href="#urls路由" class="headerlink" title="urls路由"></a>urls路由</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">urlpatterns = [</span><br><span class="line"></span><br><span class="line">    url(<span class="string">r&#x27;^$&#x27;</span>, views.index,name=<span class="string">&quot;index&quot;</span>),</span><br><span class="line">    url(<span class="string">r&#x27;^citys$&#x27;</span>, views.citys,name=<span class="string">&quot;citys&quot;</span>),</span><br><span class="line">    <span class="comment"># 获取城市信息的地址</span></span><br><span class="line">    url(<span class="string">r&#x27;^get/city$&#x27;</span>, views.get_city,name=<span class="string">&quot;get_city&quot;</span>),</span><br><span class="line">]</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="前台界面"><a href="#前台界面" class="headerlink" title="前台界面"></a>前台界面</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">&lt;斯科瑞破特 type=&quot;text/java斯科瑞破特&quot; src=&quot;/static/jquery-1.8.3.min.js&quot;&gt;&lt;/斯科瑞破特&gt;</span><br><span class="line">&lt;斯科瑞破特&gt;</span><br><span class="line">    // 第一步 获取选框 绑定称职时间</span><br><span class="line">    // 这个绑定事件绑定不了动态加载的元素</span><br><span class="line">     大括号 警号 刀乐符 (&#x27;斯莱克特&#x27;).称职(方可神 () 大括号开始 警号 大括号回</span><br><span class="line">    // 所以我们不用这个了,我们用一个或者的方法</span><br><span class="line">    //</span><br><span class="line">    刀乐符 (&#x27;斯莱克特&#x27;).live(&#x27;称职&#x27;,方可神 () &#123;</span><br><span class="line">        // 获取当前选中的城市id</span><br><span class="line">        哇 cid = 刀乐符(this).哇();</span><br><span class="line">        // 发送ajax</span><br><span class="line">        大括号开始 警号 刀乐符 .get(&#x27;/get/city/&#x27;,);警号 大括号回</span><br><span class="line"></span><br><span class="line">        刀乐符.get(&#x27;大括号开始百分号 url &quot;get_city&quot; 百分号大括号结束&#x27;,大括号开始&#x27;cid&#x27;:cid大括号结束,方可神 (data) 大括号开始</span><br><span class="line">            console.log(data);</span><br><span class="line">            // 动态创建下拉选框</span><br><span class="line">            // 这叫创建标签</span><br><span class="line">            哇 sel = 刀乐符(&#x27;&lt;斯莱克特&gt;&lt;/斯莱克特&gt;&#x27;);</span><br><span class="line">            // 定义选项</span><br><span class="line">            var ops = &#x27;<span class="tag">&lt;<span class="name">option</span>&gt;</span>--请选择--<span class="tag">&lt;/<span class="name">option</span>&gt;</span>&#x27;;</span><br><span class="line">            for (var i = 0; i &lt; data.length; i++) 大括号开始</span><br><span class="line">                ops += &#x27;<span class="tag">&lt;<span class="name">option</span> <span class="attr">value</span>=<span class="string">&quot;&#x27;+data[i].id+&#x27;&quot;</span>&gt;</span>&#x27;+data[i].name+&#x27;<span class="tag">&lt;/<span class="name">option</span>&gt;</span>&#x27;;</span><br><span class="line">            大括号结束</span><br><span class="line"></span><br><span class="line">            // 吧定义的选项设置到下拉框中</span><br><span class="line">            sel.html(ops);</span><br><span class="line">            // 吧创建的html添加到页面中</span><br><span class="line">            刀乐符(&#x27;body&#x27;).append(sel);</span><br><span class="line">        大括号结束,&#x27;json&#x27;)</span><br><span class="line">    大括号结束)</span><br><span class="line">&lt;/斯科瑞破特&gt;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>58到家MySQL军规升级版</title>
      <link href="database/mysql/mysql-58-rules/"/>
      <url>database/mysql/mysql-58-rules/</url>
      
        <content type="html"><![CDATA[<h3 id="一、基础规范"><a href="#一、基础规范" class="headerlink" title="一、基础规范"></a>一、基础规范</h3><h5 id="表存储引擎必须使用InnoDB"><a href="#表存储引擎必须使用InnoDB" class="headerlink" title="表存储引擎必须使用InnoDB"></a>表存储引擎必须使用InnoDB</h5><h5 id="表字符集默认使用utf8，必要时候使用utf8mb4"><a href="#表字符集默认使用utf8，必要时候使用utf8mb4" class="headerlink" title="表字符集默认使用utf8，必要时候使用utf8mb4"></a>表字符集默认使用utf8，必要时候使用utf8mb4</h5><p>解读：</p><p>（1）通用，无乱码风险，汉字3字节，英文1字节</p><p>（2）utf8mb4是utf8的超集，有存储4字节例如表情符号时，使用它</p><h5 id="禁止使用存储过程，视图，触发器，Event"><a href="#禁止使用存储过程，视图，触发器，Event" class="headerlink" title="禁止使用存储过程，视图，触发器，Event"></a>禁止使用存储过程，视图，触发器，Event</h5><p>解读：</p><p>（1）对数据库性能影响较大，互联网业务，能让站点层和服务层干的事情，不要交到数据库层</p><p>（2）调试，排错，迁移都比较困难，扩展性较差</p><h5 id="禁止在数据库中存储大文件，例如照片，可以将大文件存储在对象存储系统，数据库中存储路径"><a href="#禁止在数据库中存储大文件，例如照片，可以将大文件存储在对象存储系统，数据库中存储路径" class="headerlink" title="禁止在数据库中存储大文件，例如照片，可以将大文件存储在对象存储系统，数据库中存储路径"></a>禁止在数据库中存储大文件，例如照片，可以将大文件存储在对象存储系统，数据库中存储路径</h5><h5 id="禁止在线上环境做数据库压力测试"><a href="#禁止在线上环境做数据库压力测试" class="headerlink" title="禁止在线上环境做数据库压力测试"></a>禁止在线上环境做数据库压力测试</h5><h5 id="测试，开发，线上数据库环境必须隔离"><a href="#测试，开发，线上数据库环境必须隔离" class="headerlink" title="测试，开发，线上数据库环境必须隔离"></a>测试，开发，线上数据库环境必须隔离</h5><h3 id="二、命名规范"><a href="#二、命名规范" class="headerlink" title="二、命名规范"></a>二、命名规范</h3><h5 id="库名，表名，列名必须用小写，采用下划线分隔"><a href="#库名，表名，列名必须用小写，采用下划线分隔" class="headerlink" title="库名，表名，列名必须用小写，采用下划线分隔"></a>库名，表名，列名必须用小写，采用下划线分隔</h5><p>解读：abc，Abc，ABC都是给自己埋坑</p><h5 id="库名，表名，列名必须见名知义，长度不要超过32字符"><a href="#库名，表名，列名必须见名知义，长度不要超过32字符" class="headerlink" title="库名，表名，列名必须见名知义，长度不要超过32字符"></a>库名，表名，列名必须见名知义，长度不要超过32字符</h5><p>解读：tmp，wushan谁TM知道这些库是干嘛的</p><h5 id="库备份必须以bak为前缀，以日期为后缀"><a href="#库备份必须以bak为前缀，以日期为后缀" class="headerlink" title="库备份必须以bak为前缀，以日期为后缀"></a>库备份必须以bak为前缀，以日期为后缀</h5><p>从库必须以-s为后缀</p><p>备库必须以-ss为后缀</p><h3 id="三、表设计规范"><a href="#三、表设计规范" class="headerlink" title="三、表设计规范"></a>三、表设计规范</h3><h5 id="单实例表个数必须控制在2000个以内"><a href="#单实例表个数必须控制在2000个以内" class="headerlink" title="单实例表个数必须控制在2000个以内"></a>单实例表个数必须控制在2000个以内</h5><h5 id="单表分表个数必须控制在1024个以内"><a href="#单表分表个数必须控制在1024个以内" class="headerlink" title="单表分表个数必须控制在1024个以内"></a>单表分表个数必须控制在1024个以内</h5><h5 id="表必须有主键，推荐使用UNSIGNED整数为主键"><a href="#表必须有主键，推荐使用UNSIGNED整数为主键" class="headerlink" title="表必须有主键，推荐使用UNSIGNED整数为主键"></a>表必须有主键，推荐使用UNSIGNED整数为主键</h5><p>潜在坑：删除无主键的表，如果是row模式的主从架构，从库会挂住</p><h5 id="禁止使用外键，如果要保证完整性，应由应用程式实现"><a href="#禁止使用外键，如果要保证完整性，应由应用程式实现" class="headerlink" title="禁止使用外键，如果要保证完整性，应由应用程式实现"></a>禁止使用外键，如果要保证完整性，应由应用程式实现</h5><p>解读：外键使得表之间相互耦合，影响update/delete等SQL性能，有可能造成死锁，高并发情况下容易成为数据库瓶颈</p><h5 id="建议将大字段，访问频度低的字段拆分到单独的表中存储，分离冷热数据"><a href="#建议将大字段，访问频度低的字段拆分到单独的表中存储，分离冷热数据" class="headerlink" title="建议将大字段，访问频度低的字段拆分到单独的表中存储，分离冷热数据"></a>建议将大字段，访问频度低的字段拆分到单独的表中存储，分离冷热数据</h5><p>解读：具体参加《如何实施数据库垂直拆分》</p><h3 id="四、列设计规范"><a href="#四、列设计规范" class="headerlink" title="四、列设计规范"></a>四、列设计规范</h3><h5 id="根据业务区分使用tinyint-int-bigint，分别会占用1-4-8字节"><a href="#根据业务区分使用tinyint-int-bigint，分别会占用1-4-8字节" class="headerlink" title="根据业务区分使用tinyint/int/bigint，分别会占用1/4/8字节"></a>根据业务区分使用tinyint/int/bigint，分别会占用1/4/8字节</h5><h5 id="根据业务区分使用char-varchar"><a href="#根据业务区分使用char-varchar" class="headerlink" title="根据业务区分使用char/varchar"></a>根据业务区分使用char/varchar</h5><p>解读：</p><p>（1）字段长度固定，或者长度近似的业务场景，适合使用char，能够减少碎片，查询性能高</p><p>（2）字段长度相差较大，或者更新较少的业务场景，适合使用varchar，能够减少空间</p><h5 id="根据业务区分使用datetime-timestamp"><a href="#根据业务区分使用datetime-timestamp" class="headerlink" title="根据业务区分使用datetime/timestamp"></a>根据业务区分使用datetime/timestamp</h5><p>解读：前者占用5个字节，后者占用4个字节，存储年使用YEAR，存储日期使用DATE，存储时间使用datetime</p><h5 id="必须把字段定义为NOT-NULL并设默认值"><a href="#必须把字段定义为NOT-NULL并设默认值" class="headerlink" title="必须把字段定义为NOT NULL并设默认值"></a>必须把字段定义为NOT NULL并设默认值</h5><p>解读：</p><p>（1）NULL的列使用索引，索引统计，值都更加复杂，MySQL更难优化</p><p>（2）NULL需要更多的存储空间</p><p>（3）NULL只能采用IS NULL或者IS NOT NULL，而在=/!=/in/not in时有大坑</p><h5 id="使用INT-UNSIGNED存储IPv4，不要用char-15"><a href="#使用INT-UNSIGNED存储IPv4，不要用char-15" class="headerlink" title="使用INT UNSIGNED存储IPv4，不要用char(15)"></a>使用INT UNSIGNED存储IPv4，不要用char(15)</h5><h5 id="使用varchar-20-存储手机号，不要使用整数"><a href="#使用varchar-20-存储手机号，不要使用整数" class="headerlink" title="使用varchar(20)存储手机号，不要使用整数"></a>使用varchar(20)存储手机号，不要使用整数</h5><p>解读：</p><p>（1）牵扯到国家代号，可能出现+/-/()等字符，例如+86</p><p>（2）手机号不会用来做数学运算</p><p>（3）varchar可以模糊查询，例如like ‘138%’</p><h5 id="使用TINYINT来代替ENUM"><a href="#使用TINYINT来代替ENUM" class="headerlink" title="使用TINYINT来代替ENUM"></a>使用TINYINT来代替ENUM</h5><p>解读：ENUM增加新值要进行DDL操作</p><h3 id="五、索引规范"><a href="#五、索引规范" class="headerlink" title="五、索引规范"></a>五、索引规范</h3><h5 id="唯一索引使用uniq-字段名-来命名"><a href="#唯一索引使用uniq-字段名-来命名" class="headerlink" title="唯一索引使用uniq_[字段名]来命名"></a>唯一索引使用uniq_[字段名]来命名</h5><h5 id="非唯一索引使用idx-字段名-来命名"><a href="#非唯一索引使用idx-字段名-来命名" class="headerlink" title="非唯一索引使用idx_[字段名]来命名"></a>非唯一索引使用idx_[字段名]来命名</h5><h5 id="单张表索引数量建议控制在5个以内"><a href="#单张表索引数量建议控制在5个以内" class="headerlink" title="单张表索引数量建议控制在5个以内"></a>单张表索引数量建议控制在5个以内</h5><p>解读：</p><p>（1）互联网高并发业务，太多索引会影响写性能</p><p>（2）生成执行计划时，如果索引太多，会降低性能，并可能导致MySQL选择不到最优索引</p><p>（3）异常复杂的查询需求，可以选择ES等更为适合的方式存储</p><h5 id="组合索引字段数不建议超过5个"><a href="#组合索引字段数不建议超过5个" class="headerlink" title="组合索引字段数不建议超过5个"></a>组合索引字段数不建议超过5个</h5><p>解读：如果5个字段还不能极大缩小row范围，八成是设计有问题</p><h5 id="不建议在频繁更新的字段上建立索引"><a href="#不建议在频繁更新的字段上建立索引" class="headerlink" title="不建议在频繁更新的字段上建立索引"></a>不建议在频繁更新的字段上建立索引</h5><h5 id="非必要不要进行JOIN查询，如果要进行JOIN查询，被JOIN的字段必须类型相同，并建立索引"><a href="#非必要不要进行JOIN查询，如果要进行JOIN查询，被JOIN的字段必须类型相同，并建立索引" class="headerlink" title="非必要不要进行JOIN查询，如果要进行JOIN查询，被JOIN的字段必须类型相同，并建立索引"></a>非必要不要进行JOIN查询，如果要进行JOIN查询，被JOIN的字段必须类型相同，并建立索引</h5><p>解读：踩过因为JOIN字段类型不一致，而导致全表扫描的坑么？</p><h5 id="理解组合索引最左前缀原则，避免重复建设索引，如果建立了-a-b-c-，相当于建立了-a-a-b-a-b-c"><a href="#理解组合索引最左前缀原则，避免重复建设索引，如果建立了-a-b-c-，相当于建立了-a-a-b-a-b-c" class="headerlink" title="理解组合索引最左前缀原则，避免重复建设索引，如果建立了(a,b,c)，相当于建立了(a), (a,b), (a,b,c)"></a>理解组合索引最左前缀原则，避免重复建设索引，如果建立了(a,b,c)，相当于建立了(a), (a,b), (a,b,c)</h5><h3 id="六、SQL规范"><a href="#六、SQL规范" class="headerlink" title="六、SQL规范"></a>六、SQL规范</h3><h5 id="禁止使用select-，只获取必要字段"><a href="#禁止使用select-，只获取必要字段" class="headerlink" title="禁止使用select *，只获取必要字段"></a>禁止使用select *，只获取必要字段</h5><p>解读：</p><p>（1）select *会增加cpu/io/内存/带宽的消耗</p><p>（2）指定字段能有效利用索引覆盖</p><p>（3）指定字段查询，在表结构变更时，能保证对应用程序无影响</p><h5 id="insert必须指定字段，禁止使用insert-into-T-values"><a href="#insert必须指定字段，禁止使用insert-into-T-values" class="headerlink" title="insert必须指定字段，禁止使用insert into T values()"></a><code>insert</code>必须指定字段，禁止使用insert into T values()</h5><p>解读：指定字段插入，在表结构变更时，能保证对应用程序无影响</p><h5 id="隐式类型转换会使索引失效，导致全表扫描"><a href="#隐式类型转换会使索引失效，导致全表扫描" class="headerlink" title="隐式类型转换会使索引失效，导致全表扫描"></a>隐式类型转换会使索引失效，导致全表扫描</h5><h5 id="禁止在where条件列使用函数或者表达式"><a href="#禁止在where条件列使用函数或者表达式" class="headerlink" title="禁止在where条件列使用函数或者表达式"></a>禁止在where条件列使用函数或者表达式</h5><p>解读：导致不能命中索引，全表扫描</p><h5 id="禁止负向查询以及-开头的模糊查询"><a href="#禁止负向查询以及-开头的模糊查询" class="headerlink" title="禁止负向查询以及%开头的模糊查询"></a>禁止负向查询以及%开头的模糊查询</h5><p>解读：导致不能命中索引，全表扫描</p><h5 id="禁止大表JOIN和子查询"><a href="#禁止大表JOIN和子查询" class="headerlink" title="禁止大表JOIN和子查询"></a>禁止大表JOIN和子查询</h5><h5 id="同一个字段上的OR必须改写问IN，IN的值必须少于50个"><a href="#同一个字段上的OR必须改写问IN，IN的值必须少于50个" class="headerlink" title="同一个字段上的OR必须改写问IN，IN的值必须少于50个"></a>同一个字段上的OR必须改写问IN，IN的值必须少于50个</h5><h5 id="应用程序必须捕获SQL异常"><a href="#应用程序必须捕获SQL异常" class="headerlink" title="应用程序必须捕获SQL异常"></a>应用程序必须捕获SQL异常</h5><p>解读：方便定位线上问题</p><p>说明：本军规适用于并发量大，数据量大的典型互联网业务，可直接带走参考，不谢。</p><p>军规练习：为什么下列SQL不能命中phone索引？</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> uid <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> phone<span class="operator">=</span><span class="number">13811223344</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django笔记02-进阶</title>
      <link href="python/Django/note/django-note2/"/>
      <url>python/Django/note/django-note2/</url>
      
        <content type="html"><![CDATA[<h1 id="模型查询"><a href="#模型查询" class="headerlink" title="模型查询"></a>模型查询</h1><h3 id="查询集"><a href="#查询集" class="headerlink" title="查询集"></a>查询集</h3><p>在管理器上调用过滤器方法会返回查询集,查询集表示从数据库中获取的对象集合</p><p>查询集经过过滤器筛选后返回新的查询集，因此可以写成链式过滤</p><p>惰性执行：创建查询集不会带来任何数据库的访问，直到调用数据时，才会访问数据库</p><p>何时对查询集求值：迭代，序列化，与if合用</p><h3 id="返回查询集的方法，称为过滤器"><a href="#返回查询集的方法，称为过滤器" class="headerlink" title="返回查询集的方法，称为过滤器"></a>返回查询集的方法，称为过滤器</h3><ul><li>all()</li><li>filter()</li><li>exclude()</li><li>order_by()</li><li>values()：一个对象构成一个字典，然后构成一个列表返回<br>写法：<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">filter</span>(键<span class="number">1</span>=值<span class="number">1</span>,键<span class="number">2</span>=值<span class="number">2</span>)</span><br><span class="line"><span class="comment"># 等价于</span></span><br><span class="line"><span class="built_in">filter</span>(键<span class="number">1</span>=值<span class="number">1</span>).<span class="built_in">filter</span>(键<span class="number">2</span>=值<span class="number">2</span>)</span><br></pre></td></tr></table></figure></li><li>返回单个值的方法<ul><li>get()：返回单个满足条件的对象<ul><li>如果未找到会引发”模型类.DoesNotExist”异常</li><li>如果多条被返回，会引发”模型类.MultipleObjectsReturned”异常</li></ul></li><li>count()：返回当前查询的总条数</li><li>first()：返回第一个对象</li><li>last()：返回最后一个对象</li><li>exists()：判断查询集中是否有数据，如果有则返回True<h3 id="限制查询集"><a href="#限制查询集" class="headerlink" title="限制查询集"></a>限制查询集</h3></li></ul></li><li>查询集返回列表，可以使用下标的方式进行限制，等同于sql中的limit和offset子句</li><li>注意：不支持负数索引</li><li>使用下标后返回一个新的查询集，不会立即执行查询</li><li>如果获取一个对象，直接使用[0]，等同于[0:1].get()，但是如果没有数据，[0]引发IndexError异常，[0:1].get()引发DoesNotExist异常  <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#这会返回前5个对象 LIMIT 5</span></span><br><span class="line">Entry.objects.<span class="built_in">all</span>()[:<span class="number">5</span>]</span><br><span class="line"><span class="comment">#这将返回第六个到第十个对象 OFFSET 5 LIMIT 5</span></span><br><span class="line">Entry.objects.<span class="built_in">all</span>()[<span class="number">5</span>:<span class="number">10</span>]    </span><br></pre></td></tr></table></figure><h1 id="字段查询"><a href="#字段查询" class="headerlink" title="字段查询"></a>字段查询</h1></li><li>实现where子名，作为方法filter()、exclude()、get()的参数</li><li>语法：属性名称__比较运算符=值</li><li>表示两个下划线，左侧是属性名称，右侧是比较类型</li><li>对于外键，使用“属性名_id”表示外键的原始值</li><li>转义：like语句中使用了%与，匹配数据中的%与，在过滤器中直接写，例如：filter(title__contains=”%”)=&gt;where title like ‘%%%’，表示查找标题中包含%的<h1 id="用Q对象进行复杂查找"><a href="#用Q对象进行复杂查找" class="headerlink" title="用Q对象进行复杂查找"></a>用Q对象进行复杂查找</h1>关键字参数查询 - 输入filter()等 - 是“AND”编辑在一起的。如果您需要执行更复杂的查询（例如，带有OR语句的查询），则可以使用。Qobjects</li></ul><p>例如 查询or“或”的对象</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Q对象 </span></span><br><span class="line"><span class="keyword">from</span> django.db.models <span class="keyword">import</span> Q</span><br><span class="line"></span><br><span class="line">ob = Goods.objects.<span class="built_in">filter</span>(Q(id__contains=v)|Q(title__contains=v))</span><br></pre></td></tr></table></figure><h1 id="模型的关系"><a href="#模型的关系" class="headerlink" title="模型的关系"></a>模型的关系</h1><p>模型与模型之间的关系 或者理解为 表与表之间的关系</p><h2 id="例如-班级与学员-文章与类型-新闻与新闻分类"><a href="#例如-班级与学员-文章与类型-新闻与新闻分类" class="headerlink" title="例如:班级与学员 文章与类型 新闻与新闻分类"></a>例如:班级与学员 文章与类型 新闻与新闻分类</h2><h2 id="有哪些关系"><a href="#有哪些关系" class="headerlink" title="有哪些关系?"></a>有哪些关系?</h2><h3 id="一对一"><a href="#一对一" class="headerlink" title="一对一"></a>一对一</h3><ul><li>就是一个表中数据与另外一个表中的数据相关联的,并且只与一条数据关联</li><li>例如: 你来XDL学习,哪个介绍老师,哪分配哪个班级,哪个讲师 反正总之你的各种信息<ul><li>学生信息: 姓名 性别 年龄 手机号 学历</li><li>学员详情信息: 籍贯 住址 家属联系方式…</li></ul></li><li>如何实现模型的关系:这就是一对一的关系,有一个学员信息,就有一个详细的信息 一个主表中有一个字段uid,用于存储另一个表的id,这样两个表格就一一对应起来了,这个用于联系两张表格的字段,我们一般称为<code>外键</code>,这个外键就是另一张表中的主键ID        - 外键有物理外键,和逻辑外键,我们这个随便写的就是逻辑外键,这个是通过业务逻辑写进去的,使用的时候推荐使用逻辑外键</li><li>因为物理外键会,不是物理外键,外键会产生表与表直接的强耦合,可能会在并发时造成死锁,会造成程序的阻塞</li><li>在数据库比较复杂的时候,或者一些大型的网站,绝对不允许使用外键</li><li> 在<a href="https://victorfengming.gitee.io/blog/mysql-58-rules/">58到家MySQL军规升级版</a>中说过:<a href="https://victorfengming.gitee.io/blog/mysql-58-rules/#%E7%A6%81%E6%AD%A2%E4%BD%BF%E7%94%A8%E5%A4%96%E9%94%AE%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BF%9D%E8%AF%81%E5%AE%8C%E6%95%B4%E6%80%A7%E5%BA%94%E7%94%B1%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BC%8F%E5%AE%9E%E7%8E%B0">禁止使用外键，如果要保证完整性，应由应用程式实现</a></li><li>在<a href="https://victorfengming.gitee.io/blog/mysql-58-rules/">58到家MySQL军规升级版</a>中提到: <a href="https://victorfengming.gitee.io/blog/mysql-58-rules/#%E7%A6%81%E6%AD%A2%E4%BD%BF%E7%94%A8select-%E5%8F%AA%E8%8E%B7%E5%8F%96%E5%BF%85%E8%A6%81%E5%AD%97%E6%AE%B5">禁止使用select *，只获取必要字段</a> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 在用户详情表中，关联用户表，让两个表的数据产生联系</span></span><br><span class="line"><span class="comment"># 第一个参数：是被关联的模型名称</span></span><br><span class="line"><span class="comment"># 第二个参数：当user用户表中的一条数据被删除的时候</span></span><br><span class="line"><span class="comment"># ，与之对应的详情表数据也会被删除,</span></span><br><span class="line"><span class="comment"># 说白了就是同步记录删除学生了还要啥学生详情啊</span></span><br><span class="line">uid = models.OneToOneField(Stu, on_delete=models.CASCADE)</span><br><span class="line"><span class="comment"># 这里在Stu不用引号,要是换了顺序,</span></span><br><span class="line"><span class="comment"># 就是Stu在下面了,就要加上引号了,不然找不到</span></span><br><span class="line"><span class="comment"># 因为咱们python并没有类或者函数的欲仙加载,毕竟是脚本语言嘛,还想咋地!</span></span><br><span class="line"><span class="comment"># 那你还能在类定义之前去实例化对象啊, 你不得先定义在用啊</span></span><br></pre></td></tr></table></figure></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建视图函数 演示一对一模型关系的操作</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">onetoone</span>(<span class="params">request</span>):</span></span><br><span class="line">   <span class="comment"># 添加</span></span><br><span class="line">    <span class="comment"># 创建学员信息</span></span><br><span class="line">    ob = Stu(sname=<span class="string">&#x27;李四&#x27;</span>,age=<span class="number">24</span>)</span><br><span class="line">    ob.save()</span><br><span class="line">    <span class="comment"># 添加学员详情信息</span></span><br><span class="line">    obi = StuInfo()</span><br><span class="line">    obi.jiguan = <span class="string">&quot;山西&quot;</span></span><br><span class="line">    obi.xueli = <span class="string">&#x27;大专&#x27;</span></span><br><span class="line">    <span class="comment"># 注意在给外键添加数据时,</span></span><br><span class="line">    <span class="comment"># 只能选择对象,不能设为对象的id</span></span><br><span class="line">    obi.uid = ob</span><br><span class="line">    obi.save()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 查询</span></span><br><span class="line">    ob = Stu.objects.first()</span><br><span class="line">    print(ob.sname)</span><br><span class="line">    <span class="comment"># 与之关联的模型类全小写就可以了</span></span><br><span class="line">    <span class="comment"># ,另一个对象就出来了</span></span><br><span class="line">    print(ob.stuinfo.xueli)</span><br><span class="line">    <span class="comment"># 通过学员 获取学员详情对象</span></span><br><span class="line">    print(ob.stuinfo.jiguan)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 通过学员详情,获取学员信息</span></span><br><span class="line">    ob = StuInfo.objects.last()</span><br><span class="line">    print(ob.jiguan)</span><br><span class="line">    print(ob.uid)</span><br><span class="line">    print(ob.uid.sname)</span><br><span class="line">    print(ob.uid.age)</span><br><span class="line">    <span class="comment"># 有外键的一方使用外键</span></span><br><span class="line">    <span class="comment"># 没有外键的一方,使用类名小写</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 删除</span></span><br><span class="line">    <span class="comment"># 删除一个表中的记录,应该同步都删除</span></span><br><span class="line">    ob = StuInfo.objects.last()</span><br><span class="line">    ob.delete()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> HttpResponse(<span class="string">&#x27;演示 一对一模型关系的操作&#x27;</span>)</span><br></pre></td></tr></table></figure><h3 id="一对多"><a href="#一对多" class="headerlink" title="一对多"></a>一对多</h3><p>ForeignKey 一对多<br>举例<br>一个班级有多个学员,多个学员都在一个班级<br>一个表中的数据对应另外一个表中的多条数据,<br>一张表中多个数据对应另外一张表中的一条数据</p><h3 id="数据库只有两种操作"><a href="#数据库只有两种操作" class="headerlink" title="数据库只有两种操作"></a>数据库只有两种操作</h3><p>读 查询(方便但是慢)<br>写 添加,删除,修改    (不加索引就是最快的,没有任何提了螳螂的东西) </p><h3 id="多对多"><a href="#多对多" class="headerlink" title="多对多"></a>多对多</h3><p>一张表中的数据在另一张表中有多个,另一张表中也是有多个在这张表中</p><p>比如,一个班级有多个老师授课,一个老师去多个班级授课 </p><p>有一本书,标签,一本书有多个标签,一个标签下面有多本书</p><p>书籍:</p><table><thead><tr><th>id</th><th>bname</th></tr></thead><tbody><tr><td>1</td><td>&lt;&lt;Python3.7从零开始学&gt;&gt;</td></tr><tr><td>2</td><td>&lt;&lt;细说PHP&gt;&gt;</td></tr><tr><td>3</td><td>&lt;&lt;细说Python数据分析&gt;&gt;</td></tr><tr><td></td><td></td></tr><tr><td>标签:</td><td></td></tr></tbody></table><table><thead><tr><th>id</th><th>tname</th></tr></thead><tbody><tr><td>1</td><td>Python</td></tr><tr><td>2</td><td>PHP</td></tr><tr><td>3</td><td>编程语言</td></tr><tr><td>4</td><td>数据分析</td></tr></tbody></table><p>书籍和标签关系</p><table><thead><tr><th>bookid</th><th>tagid</th></tr></thead><tbody><tr><td>1</td><td>1</td></tr><tr><td>1</td><td>3</td></tr><tr><td>2</td><td>2</td></tr><tr><td>2</td><td>3</td></tr><tr><td>3</td><td>1</td></tr><tr><td>3</td><td>3</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p>Python PHP 编程语言 数据分析    </p><h3 id="视图中的请求方式"><a href="#视图中的请求方式" class="headerlink" title="视图中的请求方式"></a>视图中的请求方式</h3><p>请求报文,响应报文</p><p>一键多值情况</p><h3 id="状态保持"><a href="#状态保持" class="headerlink" title="状态保持"></a>状态保持</h3><p>HTTP协议是无状态的：每次请求都是一次新的请求，不会记得之前通信的状态<br>客户端与服务器端的一次通信，就是一次会话<br>实现状态保持的方式：在客户端或服务器端存储与会话有关的数据<br>存储方式包括cookie、session，会话一般指session对象<br>使用cookie，所有数据存储在客户端，注意不要存储敏感信息<br>推荐使用sesison方式，所有数据存储在服务器端，在客户端cookie中存储session_id<br>状态保持的目的是在一段时间内跟踪请求者的状态，可以实现跨页面访问当前请求者的数据<br>注意：不同的请求者之间不会共享这个数据，与请求者一一对应</p><h3 id="cookie和session"><a href="#cookie和session" class="headerlink" title="cookie和session"></a>cookie和session</h3><p>http请求是无状态的请求</p><p>请求中并不清楚你上一次请求的情况</p><p>在很多情况下需要记住用户的一些状态,</p><p>这个时候就需要使用回话跟踪技术,回话控制</p><h4 id="cookie"><a href="#cookie" class="headerlink" title="cookie"></a>cookie</h4><p>是在浏览器中进行数据的保存,并且在每次请求时,会携带保存的数据去访问服务器</p><p>js是可以获取cookie信息的</p><h4 id="session"><a href="#session" class="headerlink" title="session"></a>session</h4><p>sessionid是把数据存在服务端(文件,数据库,内存)<br>并且声称一个sessionid记录到cookie中,<br>session依赖cookie,这样更加的安全<br>cookie只能存储字符串类型的数据,session在python中的啥格式都行</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> standard </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django笔记01-基础</title>
      <link href="python/Django/note/django-note1/"/>
      <url>python/Django/note/django-note1/</url>
      
        <content type="html"><![CDATA[<h1 id="浅谈Web框架"><a href="#浅谈Web框架" class="headerlink" title="浅谈Web框架"></a>浅谈Web框架</h1><h3 id="一-什么是框架"><a href="#一-什么是框架" class="headerlink" title="一,什么是框架?"></a>一,什么是框架?</h3><p>软件框架就是为实现或完成某种软件开发时,提供了一些基础的软件产品,</p><p>框架的功能类似于基础设施,提供并实现最为基础的软件架构和体系</p><p>通常情况下我们依据框架来实现更为复杂的业务程序开发</p><p>一个字,框架就是程序的骨架</p><h3 id="二-框架的优缺点"><a href="#二-框架的优缺点" class="headerlink" title="二,框架的优缺点"></a>二,框架的优缺点</h3><p>可重用</p><p>成熟,稳健</p><p>可扩展性良好</p><p>选对框架很重要</p><h3 id="三-python中常见的框架"><a href="#三-python中常见的框架" class="headerlink" title="三,python中常见的框架"></a>三,python中常见的框架</h3><p>大包大揽 <code>Django</code> 被官方称之为完美主义者的Web框架。</p><p>力求精简 <code>web.py</code>和<code>Tornado</code></p><p>新生代微框架 <code>Flask</code>和<code>Bottle</code></p><h3 id="MVC设计模式"><a href="#MVC设计模式" class="headerlink" title="MVC设计模式"></a>MVC设计模式</h3><p>MVC实现了前后端和数据的分离,程序的解耦合,实现了程序的可扩展性,可维护性</p><table><thead><tr><th>英文</th><th>中文</th><th>针对部分</th><th>作用</th></tr></thead><tbody><tr><td>Model</td><td>模型</td><td>是针对数据库层面的</td><td>程序调用模型,直接操作继承model的模型对象</td></tr><tr><td>View</td><td>视图</td><td>是针对用户界面的数据显示</td><td>模板(hmtl)</td></tr><tr><td>Controller</td><td>控制器</td><td>针对业务逻辑的操作</td><td>python程序</td></tr></tbody></table><h3 id="MVT"><a href="#MVT" class="headerlink" title="MVT"></a>MVT</h3><table><thead><tr><th></th><th></th><th></th><th></th></tr></thead><tbody><tr><td>M</td><td>Model</td><td>模型</td><td>数据层</td></tr><tr><td>V</td><td>View</td><td>视图</td><td>业务逻辑</td></tr><tr><td>T</td><td>Template</td><td>模板</td><td>html</td></tr></tbody></table><h1 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h1><h3 id="1-认识Django"><a href="#1-认识Django" class="headerlink" title="1. 认识Django"></a>1. 认识Django</h3><p>Django是一个高级的Python Web框架，它鼓励快速开发和清洁，务实的设计。<br>由经验丰富的开发人员构建，它负责Web开发的许多麻烦，因此您可以专注于编写应用程序，而无需重新创建轮子。<br>它是免费的和开源的。<br>被官方称之为完美主义者的Web框架。<br>Django可以更快地构建更好的Web应用程序并减少代码。</p><p>官方网址：<a href="https://www.djangoproject.com/">https://www.djangoproject.com/</a></p><p>中文文档:<a href="http://python.usyiyi.cn/">http://python.usyiyi.cn/</a></p><h3 id="2-Django框架的特点："><a href="#2-Django框架的特点：" class="headerlink" title="2. Django框架的特点："></a>2. Django框架的特点：</h3><p>快速开发：Django的宗旨在于帮助开发人员快速从概念到完成应用程序。<br>安全可靠：Django认真对待安全性，帮助开发人员避免许多常见的安全错误。<br>超可伸缩性: Web上的一些最繁忙的网站利用了Django快速灵活扩展的能力。</p><h3 id="3-Django可以使用什么Python版本？"><a href="#3-Django可以使用什么Python版本？" class="headerlink" title="3. Django可以使用什么Python版本？"></a>3. Django可以使用什么Python版本？</h3><table><thead><tr><th>Django版本</th><th>Python版本</th></tr></thead><tbody><tr><td>1.8</td><td>2.7，3.2（直到2016年底），3.3, 3.4, 3.5</td></tr><tr><td>1.9, 1.10</td><td>2.7, 3.4, 3.5</td></tr><tr><td>1.11</td><td>2.7 , 3.4 , 3.5 , 3.6</td></tr><tr><td>2.0</td><td>3.5+</td></tr></tbody></table><h3 id="4-Django的开发版本"><a href="#4-Django的开发版本" class="headerlink" title="4. Django的开发版本"></a>4. Django的开发版本</h3><p>LTS : 长期稳定版</p><ul><li>2015 April 1.8</li><li>2017 April 1.11</li><li>2019 April 2.2</li></ul><h3 id="5-Django安装"><a href="#5-Django安装" class="headerlink" title="5. Django安装"></a>5. Django安装</h3><p>作为Python Web框架，Django需要Python，在安装Python同时需要安装pip。</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 在线安装Django</span><br><span class="line">pip3 install Django</span><br><span class="line"># 检测当前是否安装Django及版本</span><br><span class="line">python3 -m django --version</span><br><span class="line"><span class="number">1</span>.<span class="number">11</span>.<span class="number">7</span></span><br></pre></td></tr></table></figure><p>这里可以使用 -i 参数来指定镜像源位置</p><h3 id="6-使用Django框架搭建项目"><a href="#6-使用Django框架搭建项目" class="headerlink" title="6. 使用Django框架搭建项目"></a>6. 使用Django框架搭建项目</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 在一个目录中执行一下命令,就会创建一个web项目目录</span></span><br><span class="line">django-admin startproject web</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 进入到web文件夹中,执行以下命令,启动项目</span></span><br><span class="line">python3 manage.py runserver</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 接下来就可以在浏览器中访问了</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="Django入门"><a href="#Django入门" class="headerlink" title="Django入门"></a>Django入门</h1><h3 id="创建一个应用"><a href="#创建一个应用" class="headerlink" title="创建一个应用"></a>创建一个应用</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">python3 manage.py startapp home</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 以上命令会在项目文件夹中创建一个目录home</span></span><br></pre></td></tr></table></figure><h3 id="请求的流程"><a href="#请求的流程" class="headerlink" title="请求的流程"></a>请求的流程</h3><p>用户输入url地址发起请求,服务器接受到请求后,交给跟路由(项目同名目录下的urls.py)</p><h3 id="使用模板文件"><a href="#使用模板文件" class="headerlink" title="使用模板文件"></a>使用模板文件</h3><h1 id="URLconf路由"><a href="#URLconf路由" class="headerlink" title="URLconf路由"></a>URLconf路由</h1><h3 id="路由的定义"><a href="#路由的定义" class="headerlink" title="路由的定义"></a>路由的定义</h3><blockquote><p>URL ==&gt; 统一资源定位符</p><p>指得就是请求的(URL)地址</p><p><a href="http://python.itxdl.cn/html/tutorial/">http://python.itxdl.cn/html/tutorial/</a></p><p><a href="http://python.itxdl.cn/html/teachers/">http://python.itxdl.cn/html/teachers/</a></p><p>可以在项目中指定请求的url地址,来交给对应的试图函数进行解析</p></blockquote><h3 id="路由的特点"><a href="#路由的特点" class="headerlink" title="路由的特点"></a>路由的特点</h3><blockquote><p>路由就是在urls中进行规则的配置</p><p>按照从上往下的顺序来执行</p><p>如果匹配到,则假装指定的视图函数来执行</p><p>如果匹配不到,则抛出404 page not found</p></blockquote><h3 id="路由参数"><a href="#路由参数" class="headerlink" title="路由参数"></a>路由参数</h3><blockquote><p>路由参数就是在定义规则时,使用小括号<code>()</code>括起来的内容,将作为参数传递给视图函数</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 路由规则</span></span><br><span class="line">url(<span class="string">r&#x27;^article/(\d)$&#x27;</span>, views.article),</span><br><span class="line"><span class="comment"># 视图函数</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">article</span>(<span class="params">request,para</span>):</span></span><br><span class="line">    <span class="keyword">return</span> HttpResponse(<span class="string">&#x27;接受到的参数是:&#x27;</span>+para)</span><br></pre></td></tr></table></figure><h3 id="命名组-命名参数"><a href="#命名组-命名参数" class="headerlink" title="命名组,命名参数"></a>命名组,命名参数</h3><blockquote><p>和路由参数一样是用来获取url中路径作为参数来使用</p><p>不同的是,命名组会把当前参数作为,关键字参数传递给视图函数,</p><p>因此对应的视图函数,必须有关键字参数</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 命名组 使用?P&lt;变量名&gt;方式来定义</span></span><br><span class="line">url(<span class="string">r&#x27;abc/(?P&lt;aa&gt;[0-9]+/$&#x27;</span>,view.abc_2003)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在对应的视图函数中则必须有对应的关键字</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">abc_2003</span>(<span class="params">request,aa</span>):</span></span><br><span class="line">    print(aa)</span><br><span class="line">    <span class="keyword">return</span> HttpResponse(<span class="string">&#x27;abc_2003&#x27;</span>)</span><br></pre></td></tr></table></figure><h3 id="指定用于视图参数的默认值"><a href="#指定用于视图参数的默认值" class="headerlink" title="指定用于视图参数的默认值"></a>指定用于视图参数的默认值</h3><p>两个路由指向同一个视图函数</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 路由</span></span><br><span class="line">url(<span class="string">r&#x27;^user/index/(?P&lt;page&gt;[0-9]+)/$&#x27;</span>, views.user_index),</span><br><span class="line">url(<span class="string">r&#x27;^user/index/$&#x27;</span>, views.user_index),</span><br><span class="line"></span><br><span class="line"><span class="comment"># 视图函数</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">user_index</span>(<span class="params">request,page=<span class="number">1</span></span>):</span></span><br><span class="line">    print(page)</span><br><span class="line">    <span class="keyword">return</span> HttpResponse(<span class="string">&#x27;用户列表数据的显示&#x27;</span>+page)    </span><br></pre></td></tr></table></figure><h1 id="Model模型"><a href="#Model模型" class="headerlink" title="Model模型"></a>Model模型</h1><h3 id="数据库配置"><a href="#数据库配置" class="headerlink" title="数据库配置"></a>数据库配置</h3><ol><li>安装mysql</li><li>创建库,指定字符集</li><li>安装pymysql</li><li>在settings.py的同级目录中找到__init__.py文件,声明pymysql</li><li>在settings.py文件中配置 数据库</li><li>在settings.py文件中添加当前的应用</li></ol><h3 id="定义模型"><a href="#定义模型" class="headerlink" title="定义模型"></a>定义模型</h3><p>在模型中定义属性，会生成表中的字段<br>django会为表增加自动增长的主键列，每个模型只能有一个主键列<br>如果使用选项设置某属性为主键列后，则django不会再生成默认的主键列<br>属性命名限制</p><p>不能是python的保留关键字<br>由于django的查询方式，不允许使用连续的下划线</p><h3 id="定义步骤"><a href="#定义步骤" class="headerlink" title="定义步骤"></a>定义步骤</h3><ol><li><p>找到应用中的models.py文件</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;Create your models here.</span></span><br><span class="line"><span class="string">模型的作用,降低程序的耦合性,更换数据库就改个配置文件就行了</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Users</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">    username = models.CharField(max_length=<span class="number">32</span>)</span><br><span class="line">    password = models.CharField(max_length=<span class="number">32</span>)</span><br><span class="line">    email = models.CharField(max_length=<span class="number">50</span>)</span><br></pre></td></tr></table></figure></li><li><p>生成迁移文件</p></li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 manage.py makemigrations</span><br></pre></td></tr></table></figure><ol start="3"><li>执行迁移</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 manage.py makemigrate</span><br></pre></td></tr></table></figure><h1 id="View视图"><a href="#View视图" class="headerlink" title="View视图"></a>View视图</h1><h3 id="Django中的视图"><a href="#Django中的视图" class="headerlink" title="Django中的视图"></a>Django中的视图</h3><p>Django具有“视图”的概念来封装负责处理用户请求和返回响应的逻辑</p><p>视图函数或视图简而言之就是一个Python函数，它接受一个Web请求并返回一个Web响应</p><p>此响应可以是网页的HTML内容，重定向或404错误，XML文档或图像。</p><p>为了将代码放在某处，惯例是将视图views.py放在名为的文件中，放在项目或应用程序目录中</p><h3 id="在视图函数中使用模型"><a href="#在视图函数中使用模型" class="headerlink" title="在视图函数中使用模型"></a>在视图函数中使用模型</h3><ol><li>先在视图函数中导入models<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> . <span class="keyword">import</span> models</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 模型的操作演示</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">mod_demo</span>(<span class="params">request</span>):</span></span><br><span class="line">    <span class="comment"># 使用模型进行操作数据库 数据的查询操作</span></span><br><span class="line">    res = models.Users.objects.<span class="built_in">all</span>()</span><br><span class="line">    print(res)</span><br><span class="line">    <span class="comment"># &lt; QuerySet[ &lt; Users: Users object &gt;] &gt;</span></span><br><span class="line">    <span class="comment"># 一个查询集</span></span><br><span class="line">    <span class="keyword">for</span> x <span class="keyword">in</span> res:</span><br><span class="line">        print(x.username)</span><br><span class="line">    <span class="keyword">return</span> HttpResponse(<span class="string">&#x27;模型你给的操作演示&#x27;</span>)</span><br></pre></td></tr></table></figure></li></ol><h3 id="模型的操作"><a href="#模型的操作" class="headerlink" title="模型的操作"></a>模型的操作</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1查询</span></span><br><span class="line"><span class="comment"># 获取当前模型中所有的对象数据</span></span><br><span class="line"><span class="comment"># 结果为一个查询集</span></span><br><span class="line">obs = models.Stu.objects.<span class="built_in">all</span>()</span><br><span class="line"><span class="comment"># 根据id获取当前对象 结果 对象</span></span><br><span class="line">ob = models.Stu.objects.get(<span class="built_in">id</span>=<span class="number">1</span>)</span><br><span class="line"><span class="comment"># 注意:get方法能且只能返回一个对象</span></span><br><span class="line"><span class="comment"># 查多个报错,查不到也报错</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2添加</span></span><br><span class="line"><span class="comment"># 第一中方法 </span></span><br><span class="line">data = &#123;<span class="string">&#x27;name&#x27;</span>:<span class="string">&#x27;admin&#x27;</span>,<span class="string">&#x27;age&#x27;</span>,<span class="number">20</span>&#125;</span><br><span class="line">ob = models.Stu(**data)</span><br><span class="line">ob.save()</span><br><span class="line"><span class="comment"># 第二种方法</span></span><br><span class="line">ob = models.Stu()</span><br><span class="line">ob.name = <span class="string">&#x27;zhangsan&#x27;</span></span><br><span class="line">ob.age = <span class="number">20</span></span><br><span class="line">ob.save()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 推荐第一种                </span></span><br><span class="line"><span class="comment"># 3删除</span></span><br><span class="line"><span class="comment"># 获取对象.执行删除</span></span><br><span class="line">ob.delete())</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4更新</span></span><br><span class="line">ob.name = <span class="string">&#x27;aabb&#x27;</span></span><br><span class="line">ob.save())  </span><br></pre></td></tr></table></figure><h1 id="增删改查"><a href="#增删改查" class="headerlink" title="增删改查"></a>增删改查</h1><h3 id="用户管理"><a href="#用户管理" class="headerlink" title="用户管理"></a>用户管理</h3><blockquote><p>先定义一个视图函数  显示添加表单</p><p>表单吧数据提交到 执行数据添加的函数中</p><p>完成后跳转到 用户列表的视图函数中</p><p>删除链接提交到 一个执行用户删除的视图函数中k,完成后跳转列表页面</p><p>编辑链接提交到 一个显示用户数据的修改表单中</p><p>修改表单吧数据 提交到执行数据更新的视图函数中</p></blockquote><h3 id="这6个步骤对应6个路由"><a href="#这6个步骤对应6个路由" class="headerlink" title="这6个步骤对应6个路由"></a>这6个步骤对应6个路由</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 用户数据的管理</span></span><br><span class="line">url(<span class="string">r&#x27;stu/index$&#x27;</span>,views.stu_index,name=<span class="string">&#x27;stu_index&#x27;</span>),</span><br><span class="line"><span class="comment"># 执行用户的添加</span></span><br><span class="line">url(<span class="string">r&#x27;stu/insert$&#x27;</span>,views.stu_insert,name=<span class="string">&#x27;stu_insert&#x27;</span>),</span><br><span class="line"><span class="comment"># 显示添加的表单</span></span><br><span class="line">url(<span class="string">r&#x27;stu/add$&#x27;</span>,views.stu_add,name=<span class="string">&#x27;stu_add&#x27;</span>),</span><br><span class="line"><span class="comment"># 执行用户的删除</span></span><br><span class="line">url(<span class="string">r&#x27;stu/del$&#x27;</span>,views.stu_del,name=<span class="string">&#x27;stu_del&#x27;</span>),</span><br><span class="line"><span class="comment"># 用户的编辑表单</span></span><br><span class="line">url(<span class="string">r&#x27;stu/edit$&#x27;</span>,views.stu_edit,name=<span class="string">&#x27;stu_edit&#x27;</span>),</span><br><span class="line"><span class="comment"># 执行用户数据的更新</span></span><br><span class="line">url(<span class="string">r&#x27;stu/update$&#x27;</span>,views.stu_update,name=<span class="string">&#x27;stu_update&#x27;</span>),</span><br></pre></td></tr></table></figure><p>生成迁移文件时,还没有吧应用添加到配置文件中?</p><p>如果已经生成迁移文件,则直接执行迁移就可以,</p><p>另外注意,生成的迁移文件不要轻易删除</p><h3 id="模型定义"><a href="#模型定义" class="headerlink" title="模型定义"></a>模型定义</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span>(<span class="params">models.Model</span>):</span></span><br><span class="line">    <span class="keyword">pass</span></span><br></pre></td></tr></table></figure><p>在<a href="https://victorfengming.gitee.io/blog/django-note/#%E5%AE%9A%E4%B9%89%E6%A8%A1%E5%9E%8B">这里</a>已经说了</p><h3 id="模型更改问题"><a href="#模型更改问题" class="headerlink" title="模型更改问题"></a>模型更改问题</h3><blockquote><p>如果模型已经创建好了一个表,你再模型中在增加一个字段,在生成迁移文件的时候就会报出</p><p>新增的一个字段时注意,如果当前新增的字段不允许为空,并且没有设置默认值,</p><p>则会在生成迁移时</p></blockquote><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">You are trying to add a non-nullable field &#x27;age&#x27; to users without a default; we c</span><br><span class="line">an&#x27;t do that (the database needs something to populate existing rows).</span><br><span class="line">Please select a fix:</span><br><span class="line"> 1) Provide a one-off default now (will be set on all existing rows with a null v</span><br><span class="line">alue for this column)</span><br><span class="line"> 2) Quit, and let me add a default in models.py</span><br></pre></td></tr></table></figure><p>翻译过来是:</p><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">就是说,你加了一个字段,还说不能为空,然后那我之前还有挺多数据呢,这可咋整啊</span><br><span class="line">您还想添加一个非空字段,还没有默认,是不是傻?</span><br><span class="line"></span><br><span class="line">选择一个修复吧,赶紧的:</span><br><span class="line"></span><br><span class="line">1)提供一个一次性的值</span><br><span class="line"></span><br><span class="line">2)退出，修改当前新增字段</span><br><span class="line">    1. 设置默认值</span><br><span class="line">    2. 允许为空</span><br></pre></td></tr></table></figure><p>就算你表中没有数据,他也会这样问,以为他傻,他不知道你有没有数据,他也不能知道,也不需要知道</p><p>Django学习中遇到的问题（1）<a href="https://www.cnblogs.com/william126/p/7591562.html">django migration No migrations to apply</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中的yield详解</title>
      <link href="cp/python/python-yield/"/>
      <url>cp/python/python-yield/</url>
      
        <content type="html"><![CDATA[<p>阅读别人的python源码时碰到了这个yield这个关键字，各种搜索终于搞懂了，在此做一下总结：</p><ol><li>通常的for…in…循环中，in后面是一个数组，这个数组就是一个可迭代对象，类似的还有链表，字符串，文件。它可以是mylist = [1, 2, 3]，也可以是mylist = [x*x for x in range(3)]。<br>它的缺陷是所有数据都在内存中，如果有海量数据的话将会非常耗内存。</li><li>生成器是可以迭代的，但只可以读取它一次。因为用的时候才生成。比如 mygenerator = (x*x for x in range(3))，注意这里用到了()，它就不是数组，而上面的例子是[]。</li><li>我理解的生成器(generator)能够迭代的关键是它有一个next()方法，工作原理就是通过重复调用next()方法，直到捕获一个异常。可以用上面的mygenerator测试。</li><li>带有 yield 的函数不再是一个普通函数，而是一个生成器generator，可用于迭代，工作原理同上。</li><li>yield 是一个类似 return 的关键字，迭代一次遇到yield时就返回yield后面(右边)的值。重点是：下一次迭代时，从上一次迭代遇到的yield后面的代码(下一行)开始执行。</li><li>简要理解：yield就是 return 返回一个值，并且记住这个返回的位置，下次迭代就从这个位置后(下一行)开始。</li><li>带有yield的函数不仅仅只用于for循环中，而且可用于某个函数的参数，只要这个函数的参数允许迭代参数。比如array.extend函数，它的原型是array.extend(iterable)。</li><li>send(msg)与next()的区别在于send可以传递参数给yield表达式，这时传递的参数会作为yield表达式的值，而yield的参数是返回给调用者的值。——换句话说，就是send可以强行修改上一个yield表达式值。比如函数中有一个yield赋值，a = yield 5，第一次迭代到这里会返回5，a还没有赋值。第二次迭代时，使用.send(10)，那么，就是强行修改yield 5表达式的值为10，本来是5的，那么a=10</li><li>send(msg)与next()都有返回值，它们的返回值是当前迭代遇到yield时，yield后面表达式的值，其实就是当前迭代中yield后面的参数。</li><li>第一次调用时必须先next()或send(None)，否则会报错，send后之所以为None是因为这时候没有上一个yield(根据第8条)。可以认为，next()等同于send(None)。<h3 id="代码示例1"><a href="#代码示例1" class="headerlink" title="代码示例1"></a>代码示例1</h3></li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#encoding:UTF-8  </span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">yield_test</span>(<span class="params">n</span>):</span>  </span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(n):  </span><br><span class="line">        <span class="keyword">yield</span> call(i)  </span><br><span class="line">        print(<span class="string">&quot;i=&quot;</span>,i)  </span><br><span class="line">    <span class="comment">#做一些其它的事情      </span></span><br><span class="line">    print(<span class="string">&quot;do something.&quot;</span>)      </span><br><span class="line">    print(<span class="string">&quot;end.&quot;</span>)  </span><br><span class="line">  </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">call</span>(<span class="params">i</span>):</span>  </span><br><span class="line">    <span class="keyword">return</span> i*<span class="number">2</span>  </span><br><span class="line">  </span><br><span class="line"><span class="comment">#使用for循环  </span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> yield_test(<span class="number">5</span>):  </span><br><span class="line">    print(i,<span class="string">&quot;,&quot;</span>)  </span><br></pre></td></tr></table></figure><h5 id="结果是："><a href="#结果是：" class="headerlink" title="结果是："></a>结果是：</h5><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;</span><span class="bash">&gt;&gt;</span>   </span><br><span class="line">0 ,  </span><br><span class="line">i= 0  </span><br><span class="line">2 ,  </span><br><span class="line">i= 1  </span><br><span class="line">4 ,  </span><br><span class="line">i= 2  </span><br><span class="line">6 ,  </span><br><span class="line">i= 3  </span><br><span class="line">8 ,  </span><br><span class="line">i= 4  </span><br><span class="line">do something.  </span><br><span class="line">end.  </span><br><span class="line"><span class="meta">&gt;</span><span class="bash">&gt;&gt;</span> </span><br></pre></td></tr></table></figure><p>理解的关键在于：下次迭代时，代码从yield的下一跳语句开始执行。</p><h3 id="代码示例2："><a href="#代码示例2：" class="headerlink" title="代码示例2："></a>代码示例2：</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">node</span>.<span class="title">_get_child_candidates</span>(<span class="params">self, distance, min_dist, max_dist</span>):</span></span><br><span class="line">    <span class="keyword">if</span> self._leftchild <span class="keyword">and</span> distance - max_dist &lt; self._median:</span><br><span class="line">        <span class="keyword">yield</span> self._leftchild</span><br><span class="line">    <span class="keyword">if</span> self._rightchild <span class="keyword">and</span> distance + max_dist &gt;= self._median:</span><br><span class="line">        <span class="keyword">yield</span> self._rightchild</span><br></pre></td></tr></table></figure><p>与前面不同的是，这个函数中没有for循环，但它依然可以用于迭代。<br>node._get_child_candidates函数中有yield，所以它变成了一个迭代器，可以用于迭代。</p><p>执行第一次迭代时（其实就是调用next()方法），如果有左节点并且距离满足要求，会执行第一个yield，这时会返回self._leftchild并完成第一个迭代。</p><p>执行第二次迭代时，从第一个yield后面开始，如果有右节点并且距离满足要求，会执行第二个yield，这时会返回self._rightchild并完成第一个迭代。</p><p>执行第三次迭代时，第二个yield后再无代码，捕获异常，退出迭代。</p><h5 id="调用过程："><a href="#调用过程：" class="headerlink" title="调用过程："></a>调用过程：</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">result, candidates = <span class="built_in">list</span>(), [self]</span><br><span class="line"><span class="keyword">while</span> candidates:</span><br><span class="line">    node = candidates.pop()</span><br><span class="line">    distance = node._get_dist(obj)</span><br><span class="line">    <span class="keyword">if</span> distance &lt;= max_dist <span class="keyword">and</span> distance &gt;= min_dist:</span><br><span class="line">        result.extend(node._values)</span><br><span class="line">    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))</span><br><span class="line"><span class="keyword">return</span> result</span><br></pre></td></tr></table></figure><p>上面的node._get_child_candidates(self, distance, min_dist, max_dist)是放在extend()函数中作为参数的，为什么可以这么用，就因为extend函数的参数不仅仅支持array，只要它是一个迭代器就可以。它的原型是array.extend(iterable)。</p><p>作者：千若逸<br>链接：<a href="https://www.jianshu.com/p/d09778f4e055">https://www.jianshu.com/p/d09778f4e055</a><br>来源：简书<br>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。  </p>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Scrapy笔记02</title>
      <link href="python/spider/Scrapy/scrapy-note2/"/>
      <url>python/spider/Scrapy/scrapy-note2/</url>
      
        <content type="html"><![CDATA[<h3 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h3><blockquote><ol><li>Scrapy Engine:提供并发的支持-已经实现好的</li><li>Scheduler(调度器): 存储以及调度(URL+函数) = Request - 已经实现好的,不需要修改</li><li>Downloader(下载器):爬虫第三部,通过request下载返回值(HTML,JSON),RESPONSE - 已经实现好的</li><li>Spiders(蜘蛛):爬虫第四步,获取到了Response之后,需要定位具体信息 - 需要自己实现的</li><li>Item Pipeline(项目管道):存储或者是继续处理具体信息 - 需要自己实现的  </li></ol></blockquote><p>新建一个Scrapy的项目</p><p>爬虫的重点在分析网页上面,而不是在写程序上面</p><h3 id="后续内容"><a href="#后续内容" class="headerlink" title="后续内容"></a>后续内容</h3><ul><li>post请求怎么办</li><li>如何使用image pipeline</li><li>如何添加headers相关信息</li><li>如何添加代理</li><li>全网爬虫如何建立</li><li>各种中间件的内容</li><li>分布式爬虫的原理以及案例</li></ul><h3 id="scrapy数据流"><a href="#scrapy数据流" class="headerlink" title="scrapy数据流"></a>scrapy数据流</h3><blockquote><ol><li>spiders 中需要有start_urls或者start_requests,生成初始的requests,发送给Engine处理</li><li>将Request放到sheduler中存储</li><li>当并发处理有空闲的时候,Engine就会到sheduler中获取一个request,当欧昂将</li><li>将获取到的request放到Downloader中下载,会经过Downloader Middleware</li><li>通过request下载内容,之后,会生成一个response的内容 将response的内容返还给Engine</li><li>Engine将Response返还给Spiders,在Spiders中定位具体的信息,会经过中间件,Spider Middleware</li><li>返回的过程中会生成两类数据,其一是items,其二是requests(第7个requests会经过中间件,而第一个requests不会经过中间件)</li><li>如果返回值是ITEMS, 那么我们将它放入ITEM Pipeline 如果返回的是Request,将它加入到Scheduler中共</li><li>循环三到八不,知道scheduler中没有request为止</li></ol></blockquote><h3 id="中间件有什么用处"><a href="#中间件有什么用处" class="headerlink" title="中间件有什么用处?"></a>中间件有什么用处?</h3>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> spider </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>pip配置</title>
      <link href="python/collection/pip-conf/"/>
      <url>python/collection/pip-conf/</url>
      
        <content type="html"><![CDATA[<p>pycharm用户看<a href="https://blog.csdn.net/kermitJam/article/details/82315974">这里</a></p><p>很多小伙伴在ubuntu系统下,使用pip安装会很慢</p><p>以为安装源在国外服务器上面</p><p>今天小编就教大家配置成让pip默认从国内源中寻找安装包</p><p>首先Ctrl+Alt+T打开终端</p><p>进入家目录</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd ~</span><br></pre></td></tr></table></figure><p>在家目录中创建一个文件夹,命名为<code>.pip</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir .pip</span><br></pre></td></tr></table></figure><p>进入目录,并创建一个名为<code>pip.conf</code>的文件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd .pip</span><br><span class="line">touch pip.conf</span><br></pre></td></tr></table></figure><p>使用vim编辑文件内容,如下</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[global]</span><br><span class="line">index-url = https://pypi.tuna.tsinghua.edu.cn/simple</span><br><span class="line">[install]</span><br><span class="line">trusted-host=mirrors.aliyun.com</span><br></pre></td></tr></table></figure><p>使用wq保存并退出,即可</p><p>在以后使用pip安装python模块的时候,默认就从国内来进行安装了,赶紧去试一下吧!</p><p>附加:豆瓣源</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:&#x2F;&#x2F;pypi.douban.com&#x2F;simple</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>漫话：什么是协程？</title>
      <link href="comic/thread-process-coroutines/"/>
      <url>comic/thread-process-coroutines/</url>
      
        <content type="html"><![CDATA[<article class="article" id="mp-editor">    <!-- 政务处理 -->          <p data-role="original-title" style="display:none">原标题：漫画：什么是协程？</p>            <blockquote>  <p><strong><span style="font-size: 16px;">来自：程序员小灰（微信号：chengxuyuanxiaohui）</span></strong></p> </blockquote> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/8dbdcbbb819540c882cabd3ea68b6764.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/e637c0d39b70431eb3b2f719cfa3b0db.jpeg"></p> <p style="text-align: center;"><span style="font-size: 20px;"><strong>————— 第二天 —————</strong></span></p> <p><img width="auto" src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/00df3b15b0304b7383970ead818cd94e.jpeg"></p> <p><img width="auto" src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/e34e7aa5fa45477fb81042100b0aedac.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/56033fea3556416da440b44359c8ce68.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/c221bbaa328b40e8801a7a5eb89eee64.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/2f61ced9e67e49219e99dfa4f71ba07a.jpeg"></p> <p style="text-align: center;"><span style="font-size: 16px;">————————————</span></p> <p><img width="auto" src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/51d5f17023cf4ca1887acd519154d3b8.jpeg"></p> <p><img width="auto" src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/595a33594f3f46239e653bb87e43a3ae.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/73722ba028784b0f82eb19facd5b4efb.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/91a32ed35ae445e6b3e8a42919faa12d.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/ae146b4471b2486280d675cce6514e49.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/6375384b85a544ed87c8cc382ba04cad.jpeg"></p> <p style="text-align: left;"><span style="font-size: 20px;"><strong>什么是进程和线程</strong></span></p> <p><span style="font-size: 16px;">有一定基础的小伙伴们肯定都知道进程和线程。</span></p> <p><span style="font-size: 16px;">进程是什么呢？</span></p> <p><span style="font-size: 16px;">直白地讲，进程就是应用程序的启动实例。比如我们运行一个游戏，打开一个软件，就是开启了一个进程。</span></p> <p><span style="font-size: 16px;">进程拥有代码和打开的文件资源、数据资源、独立的内存空间。</span></p> <p><span style="font-size: 16px;">线程又是什么呢？</span></p> <p><span style="font-size: 16px;">线程从属于进程，是程序的实际执行者。一个进程至少包含一个主线程，也可以有更多的子线程。</span></p> <p><span style="font-size: 16px;">线程拥有自己的栈空间。</span></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/6260a7a0e05c4b19a9b7465c8e56053e.jpeg"></p> <p><span style="font-size: 16px;">有人给出了很好的归纳：</span></p> <p><strong><span style="font-size: 16px;">对操作系统来说，线程是最小的执行单元，进程是最小的资源管理单元。</span></strong></p> <p><span style="font-size: 16px;">无论进程还是线程，都是由操作系统所管理的。</span></p> <p><span style="font-size: 16px;">Java中线程具有五种状态：</span></p> <p><strong><span style="font-size: 16px;">初始化</span></strong></p> <p><strong><span style="font-size: 16px;">可运行</span></strong></p> <p><strong><span style="font-size: 16px;">运行中</span></strong></p> <p><strong><span style="font-size: 16px;">阻塞</span></strong></p> <p><strong><span style="font-size: 16px;">销毁</span></strong></p> <p><span style="font-size: 16px;">这五种状态的转化关系如下：</span></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/82539cb6fc7b45bd94c4a6e3ad858bf2.png"></p> <p><span style="font-size: 16px;">但是，线程不同状态之间的转化是谁来实现的呢？是JVM吗？</span></p> <p><span style="font-size: 16px;">并不是。JVM需要通过操作系统内核中的TCB（Thread Control Block）模块来改变线程的状态，这一过程需要耗费一定的CPU资源。</span></p> <p><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/20abc0b6d1b74e3ab6be05ee08595b11.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/4731f3c6cb1e47dc9b8caae2977c0136.jpeg"></p> <p><strong><span style="font-size: 20px;">进程和线程的痛点</span></strong></p> <p><span style="font-size: 16px;">线程之间是如何进行协作的呢？</span></p> <p><span style="font-size: 16px;">最经典的例子就是<strong>生产者/消费者模式</strong>：</span></p> <p><span style="font-size: 16px;">若干个生产者线程向队列中写入数据，若干个消费者线程从队列中消费数据。</span></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/a83040de2d0b491e9e445d981870099a.png"></p> <p><span style="font-size: 16px;">如何用java语言实现生产者/消费者模式呢？</span></p> <p><span style="font-size: 16px;">让我们来看一看代码：</span></p> <p>public class ProducerConsumerTest {</p> <ol>  <li>public static void main(String args[]) {</li>  <li>final Queue&lt;Integer&gt; sharedQueue = new LinkedList();</li>  <li>Thread producer = new Producer(sharedQueue);</li>  <li>Thread consumer = new Consumer(sharedQueue);</li>  <li>producer.start();</li>  <li>consumer.start();</li>  <li>}</li> </ol> <p>}</p> <p>class Producer extends Thread {</p> <ol>  <li>private static final int MAX_QUEUE_SIZE = 5;</li>  <li></li>  <li>private final Queue sharedQueue;</li>  <li></li>  <li>public Producer(Queue sharedQueue) {</li>  <li>super();</li>  <li>this.sharedQueue = sharedQueue;</li>  <li>}</li>  <li></li>  <li>@Override</li>  <li>public void run() {</li>  <li>for (int i = 0; i &lt; 100; i++) {</li>  <li>synchronized (sharedQueue) {</li>  <li>while (sharedQueue.size() &gt;= MAX_QUEUE_SIZE) {</li>  <li>System.out.println("队列满了，等待消费");</li>  <li>try {</li>  <li>sharedQueue.wait();</li>  <li>} catch (InterruptedException e) {</li>  <li>e.printStackTrace();</li>  <li>}</li>  <li>}</li>  <li>sharedQueue.add(i);</li>  <li>System.out.println("进行生产 : " + i);</li>  <li>sharedQueue.notify();</li>  <li>}</li>  <li>}</li>  <li>}</li> </ol> <p>}</p> <p>class Consumer extends Thread {private final Queue sharedQueue; </p> <ol>  <li>public Consumer(Queue sharedQueue) {</li>  <li>super();</li>  <li>this.sharedQueue = sharedQueue;</li>  <li>}</li>  <li></li>  <li>@Override</li>  <li>public void run() {</li>  <li>while(true) {</li>  <li>synchronized (sharedQueue) {</li>  <li>while (sharedQueue.size() == 0) {</li>  <li>try {</li>  <li>System.out.println("队列空了，等待生产");</li>  <li>sharedQueue.wait();</li>  <li>} catch (InterruptedException e) {</li>  <li>e.printStackTrace();</li>  <li>}</li>  <li>}</li>  <li>int number = sharedQueue.poll();</li>  <li>System.out.println("进行消费 : " + number );</li>  <li>sharedQueue.notify();</li>  <li>}</li>  <li>}</li>  <li>}</li> </ol> <p>}</p> <p><span style="font-size: 16px;">这段代码做了下面几件事：</span></p> <p><span style="font-size: 16px;">1.定义了一个生产者类，一个消费者类。</span></p> <p><span style="font-size: 16px;">2.生产者类循环100次，向同步队列当中插入数据。</span></p> <p><span style="font-size: 16px;">3.消费者循环监听同步队列，当队列有数据时拉取数据。</span></p> <p><span style="font-size: 16px;">4.如果队列满了（达到5个元素），生产者阻塞。</span></p> <p><span style="font-size: 16px;">5.如果队列空了，消费者阻塞。</span></p> <p><span style="font-size: 16px;">上面的代码正确地实现了生产者/消费者模式，但是却并不是一个高性能的实现。为什么性能不高呢？原因如下：</span></p> <p><span style="font-size: 16px;">1.涉及到同步锁。</span></p> <p><span style="font-size: 16px;">2.涉及到线程阻塞状态和可运行状态之间的切换。</span></p> <p><span style="font-size: 16px;">3.涉及到线程上下文的切换。</span></p> <p><span style="font-size: 16px;">以上涉及到的任何一点，都是非常耗费性能的操作。</span></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/36cac4a04ae94cef95ac28435c05ed79.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/3d525b2f0c9c48cfbc7edecbf114d9da.jpeg"></p> <p><strong><span style="font-size: 20px;">什么是协程</span></strong></p> <p><strong><span style="font-size: 16px;">协程，英文Coroutines，是一种比线程更加轻量级的存在。</span></strong><span style="font-size: 16px;">正如一个进程可以拥有多个线程一样，一个线程也可以拥有多个协程。</span></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/6765e36cc4604fba897976638af03524.jpeg"></p> <p><span style="font-size: 16px;">最重要的是，协程不是被操作系统内核所管理，而完全是由程序所控制（也就是在用户态执行）。</span></p> <p><span style="font-size: 16px;">这样带来的好处就是性能得到了很大的提升，不会像线程切换那样消耗资源。</span></p> <p><span style="font-size: 16px;">既然协程这么好，它到底是怎么来使用的呢？</span></p> <p><span style="font-size: 16px;">由于Java的原生语法中并没有实现协程（某些开源框架实现了协程，但是很少被使用），所以我们来看一看python当中对协程的实现案例，同样以生产者消费者模式为例：</span></p> <p><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/8081394d462340cebbf7a31106f63474.png"></p> <p><span style="font-size: 16px;">这段代码十分简单，即使没用过python的小伙伴应该也能基本看懂。</span></p> <p><span style="font-size: 16px;">代码中创建了一个叫做consumer的协程，并且在主线程中生产数据，协程中消费数据。</span></p> <p><span style="font-size: 16px;">其中 <strong>yield </strong>是python当中的语法。当协程执行到yield关键字时，会暂停在那一行，等到主线程调用send方法发送了数据，协程才会接到数据继续执行。</span></p> <p><span style="font-size: 16px;">但是，yield让协程暂停，和线程的阻塞是有本质区别的。协程的暂停完全由程序控制，线程的阻塞状态是由操作系统内核来进行切换。</span></p> <p><span style="font-size: 16px;">因此，<strong>协程的开销远远小于线程的开销。</strong></span></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/a10f7d4eb8fd4f4b94e3bf4f72821fdd.jpeg"></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/1aa0c04319724fd6a2f88c19e255c001.jpeg"></p> <p><strong><span style="font-size: 20px;">协程的应用</span></strong></p> <p><span style="font-size: 16px;">有哪些编程语言应用到了协程呢？我们举几个栗子：</span></p> <p><strong><span style="font-size: 16px;">Lua语言</span></strong></p> <p><span style="font-size: 16px;">Lua从5.0版本开始使用协程，通过扩展库coroutine来实现。</span></p> <p><strong><span style="font-size: 16px;">Python语言</span></strong></p> <p><span style="font-size: 16px;">正如刚才所写的代码示例，python可以通过 yield/send 的方式实现协程。在python 3.5以后，<span style="font-size: 16px;"></span><span style="font-size: 16px;">async/await 成为</span>了更好的替代方案</span><span style="font-size: 16px;">。</span></p> <p><strong><span style="font-size: 16px;">Go语言</span></strong></p> <p><span style="font-size: 16px;">Go语言对协程的实现非常强大而简洁，可以轻松创建成百上千个协程并发执行。</span></p> <p><strong><span style="font-size: 16px;">Java语言</span></strong></p> <p><span style="font-size: 16px;">如上文所说，Java语言并没有对协程的原生支持，但是某些开源框架模拟出了协程的功能，有兴趣的小伙伴可以看一看<strong>Kilim框架</strong>的源码：</span></p> <p><span style="font-size: 16px;">https://github.com/kilim/kilim</span></p> <p style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="http://5b0988e595225.cdn.sohucs.com/images/20180622/0777cd1a4feb4570ae8527d910854daf.jpeg"></p> <p><strong><span style="font-size: 16px;">几点补充：</span></strong></p> <p><span style="font-size: 16px;">1.关于协程的概念，小灰也仅仅是知道一些皮毛，希望小伙伴们多多指正。</span></p> <p><strong>2.本漫画纯属娱乐，还请大家尽量珍惜当下的工作，切勿模仿小灰的行为哦。</strong></p> <p style="text-align: center;"><span style="font-size: 16px;">—————END—————</span></p> </article>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中的虚拟环境-virtualenv</title>
      <link href="cp/python/python-venv/"/>
      <url>cp/python/python-venv/</url>
      
        <content type="html"><![CDATA[<h1 id="更低层次-virtualenv"><a href="#更低层次-virtualenv" class="headerlink" title="更低层次: virtualenv"></a>更低层次: virtualenv</h1><p>virtualenv 是一个创建隔绝的Python环境的 工具。virtualenv创建一个包含所有必要的可执行文件的文件夹，用来使用Python工程所需的包。  </p><p>它可以独立使用，代替Pipenv。  </p><h3 id="通过pip安装virtualenv："><a href="#通过pip安装virtualenv：" class="headerlink" title="通过pip安装virtualenv："></a>通过pip安装virtualenv：</h3><pre><code>$ pip install virtualenv  </code></pre><h3 id="测试您的安装："><a href="#测试您的安装：" class="headerlink" title="测试您的安装："></a>测试您的安装：</h3><pre><code>$ virtualenv --version  </code></pre><h2 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h2><h3 id="为一个工程创建一个虚拟环境："><a href="#为一个工程创建一个虚拟环境：" class="headerlink" title="为一个工程创建一个虚拟环境："></a>为一个工程创建一个虚拟环境：</h3><pre><code>$ cd my_project_folder  $ virtualenv venv  </code></pre><p><code>virtualenv venv</code> 将会在当前的目录中创建一个文件夹，包含了Python可执行文件， 以及 pip 库的一份拷贝，这样就能安装其他包了。<br>虚拟环境的名字（此例中是 venv ） 可以是任意的；若省略名字将会把文件均放在当前目录。<br>在任何您运行命令的目录中，这会创建Python的拷贝，并将之放在叫做 venv 的文件中。<br>您可以选择使用一个Python解释器（比如<code>python2.7</code>）：  </p><pre><code>$ virtualenv -p /usr/bin/python2.7 venv  </code></pre><p>或者使用<code>~/.bashrc</code>的一个环境变量将解释器改为全局性的：  </p><pre><code>$ export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python2.7  </code></pre><p>要开始使用虚拟环境，其需要被激活：  </p><pre><code>$ source venv/bin/activate  </code></pre><p>当前虚拟环境的名字会显示在提示符左侧（比如说 (venv)您的电脑:您的工程 用户名$） 以让您知道它是激活的。从现在起，任何您使用pip安装的包将会放在 ``venv 文件夹中， 与全局安装的Python隔绝开。  </p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>像平常一样安装包，比如：  </p><pre><code>$ pip install requests  </code></pre><h3 id="如果您在虚拟环境中暂时完成了工作，则可以停用它："><a href="#如果您在虚拟环境中暂时完成了工作，则可以停用它：" class="headerlink" title="如果您在虚拟环境中暂时完成了工作，则可以停用它："></a>如果您在虚拟环境中暂时完成了工作，则可以停用它：</h3><pre><code>$ deactivate  </code></pre><p>这将会回到系统默认的Python解释器，包括已安装的库也会回到默认的。<br>要删除一个虚拟环境，只需删除它的文件夹。（要这么做请执行 rm -rf venv ）<br>然后一段时间后，您可能会有很多个虚拟环境散落在系统各处，您将有可能忘记它们的名字或者位置。<br>其他注意事项<br>运行带 <code>--no-site-packages</code> 选项的 <code>virtualenv</code> 将不会包括全局安装的包。 这可用于保持包列表干净，以防以后需要访问它。（这在 virtualenv 1.7及之后是默认行为）<br>为了保持您的环境的一致性，“冷冻住（freeze）”环境包当前的状态是个好主意。要这么做，请运行：  </p><pre><code>$ pip freeze &gt; requirements.txt  </code></pre><p>这将会创建一个 requirements.txt 文件，其中包含了当前环境中所有包及 各自的版本的简单列表。<br>您可以使用 pip list 在不产生requirements文件的情况下， 查看已安装包的列表。<br>这将会使另一个不同的开发者（或者是您，如果您需要重新创建这样的环境） 在以后安装相同版本的相同包变得容易。  </p><pre><code>$ pip install -r requirements.txt  </code></pre><p>这能帮助确保安装、部署和开发者之间的一致性。<br>最后，记住在源码版本控制中排除掉虚拟环境文件夹，可在ignore的列表中加上它。 （查看 版本控制忽略）  </p><p>本文转载自:<a href="https://pythonguidecn.readthedocs.io/zh/latest/dev/virtualenvs.html">https://pythonguidecn.readthedocs.io/zh/latest/dev/virtualenvs.html</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>selenium浅析</title>
      <link href="python/spider/selenium/"/>
      <url>python/spider/selenium/</url>
      
        <content type="html"><![CDATA[<h3 id="后续内容安排"><a href="#后续内容安排" class="headerlink" title="后续内容安排"></a>后续内容安排</h3><ol><li>selenium</li><li>如果遇到了验证码处理情况(将验证码图片编程单词或者数据,调用其他人的接口实现)</li><li>如何使用代理(1-1.5)天</li><li>什么是线程,进程,协程(2天)</li><li>框架Scrapy(5天)</li></ol><h3 id="1-爬虫的五个步骤"><a href="#1-爬虫的五个步骤" class="headerlink" title="1. 爬虫的五个步骤"></a>1. 爬虫的五个步骤</h3><ul><li>需求分析</li><li>通过需求分析寻找需要的URL</li><li>通过网站的URL获取网站返回信息(HTML,JSON)</li><li>定位信息的位置<ul><li>re</li><li>xpath</li><li>css selector</li></ul></li><li>存储信息</li></ul><p>其中分析网页的过程才是最长的,但是这个分析的过程在面试中,并不容易去考察你</p><h3 id="selenium-在爬虫中的作用"><a href="#selenium-在爬虫中的作用" class="headerlink" title="selenium 在爬虫中的作用"></a>selenium 在爬虫中的作用</h3><ol><li>他能够帮助我们解决掉JavaScript动态加载的问题<br>但是selenium的问题在于他慢,贼慢</li></ol><h3 id="面试题-如何加快selenium的速度"><a href="#面试题-如何加快selenium的速度" class="headerlink" title="面试题:如何加快selenium的速度"></a>面试题:如何加快selenium的速度</h3><ol><li>记加载的资源过多,所以才会慢,关闭各种资源的加载</li></ol><h3 id="线程进程"><a href="#线程进程" class="headerlink" title="线程进程"></a>线程进程</h3><p>每一个程序的执行,都至少要包含一个进程<br>一个进程里面,至少要包含一个线程<br>那么一个线程里面至少要包含一个协程</p><h1 id="今日内容"><a href="#今日内容" class="headerlink" title="今日内容"></a>今日内容</h1><ol><li>进程池</li><li>协程</li><li>代理相关网站</li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> spider </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python实现递归修改文件扩展名</title>
      <link href="python/self_tool/python-change-extension-name/"/>
      <url>python/self_tool/python-change-extension-name/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>小编今天将博客中的markdown文件上传到<a href="https://note.youdao.com/web/">有道云笔记</a>中,发现了一个BUG:有道云中只能识别md文件格式,而markdown扩展的名的文件不能被识别,也就不能直接查看到文件的内容,所以精通python的小编当然有办法解决了,小编写了一个python脚本,轻松的实现了批量重命名操作</p><h3 id="设计思路"><a href="#设计思路" class="headerlink" title="设计思路"></a>设计思路</h3><ul><li>首先我们要列出根目录中的文件夹和文件列表</li><li>判断是否为文件夹<ul><li>是文件进行更改操作</li><li>不是文件,进行递归文件夹 </li></ul></li><li>然后获取文件名,去除掉文件名中的扩展名</li><li>更改为自己制定的新的扩展名</li></ul><h3 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by 秋叶夏风</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;&quot;批量修改文件扩展名(递归)&quot;&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入系统模块</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">isFile</span>(<span class="params">filePath</span>):</span>  <span class="comment"># 修改文件扩展名</span></span><br><span class="line">    filename = filePath.split(<span class="string">&#x27;\\&#x27;</span>)[-<span class="number">1</span>]  <span class="comment"># 拆分文件路径获得文件名</span></span><br><span class="line">    fatherPath = filePath.replace(filename, <span class="string">&#x27;&#x27;</span>)  <span class="comment"># 获得父级路径</span></span><br><span class="line">    split = os.path.splitext(filename)  <span class="comment"># 拆分文件名和扩展名</span></span><br><span class="line">    newname = split[<span class="number">0</span>] + <span class="string">&#x27;.md&#x27;</span>  <span class="comment"># 生成新文件名</span></span><br><span class="line">    os.chdir(fatherPath)  <span class="comment"># 改变当前工作目录到指定的路径</span></span><br><span class="line">    os.rename(filename, newname)  <span class="comment"># 文件重命名</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">openDir</span>(<span class="params">filePath</span>):</span>  <span class="comment"># 递归文件夹</span></span><br><span class="line">    pathDir = os.listdir(filePath)  <span class="comment"># 返回包含的文件或文件夹的名字的列表</span></span><br><span class="line">    <span class="keyword">for</span> filename <span class="keyword">in</span> pathDir:  <span class="comment"># 遍历列表</span></span><br><span class="line">        childPath = os.path.join(filePath, filename)</span><br><span class="line">        <span class="comment"># 判断是否为文件夹</span></span><br><span class="line">        <span class="keyword">if</span> os.path.isfile(childPath):</span><br><span class="line">            isFile(childPath)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            openDir(childPath)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    rootDir = <span class="string">&#x27;D:\\PycharmProjects\\victorfengming.github.io\\_posts&#x27;</span>  <span class="comment"># 根目录</span></span><br><span class="line">    pathDir = os.listdir(rootDir)  <span class="comment"># 列出根目录下所有内容</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> allDir <span class="keyword">in</span> pathDir:  <span class="comment"># 遍历列表</span></span><br><span class="line">        filepath = os.path.join(rootDir, allDir)  <span class="comment"># 文件路径合成</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 判断是否为文件夹</span></span><br><span class="line">        <span class="keyword">if</span> os.path.isfile(filepath):</span><br><span class="line">            isFile(filepath)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            openDir(filepath)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JavaWeb笔记05</title>
      <link href="java/JavaWeb/note-Thread-safe/"/>
      <url>java/JavaWeb/note-Thread-safe/</url>
      
        <content type="html"><![CDATA[<h3 id="线程安全问题"><a href="#线程安全问题" class="headerlink" title="线程安全问题:"></a>线程安全问题:</h3><p>Servlet的service方法,每次被请求是,调用.</p><p>这个调用很特殊,是在新的子线程中调用的,当service方法执行完毕,子线程死亡了.</p><p>可以简单的理解为:service方法每次执行都是一个新的线程.</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.xdl.demo1;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.ServletException;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.annotation.WebServlet;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServlet;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> xdl_javaweb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.xdl.demo1</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-15 13:30</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;线程锁测试&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@WebServlet(&quot;/s1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Servlet1</span> <span class="keyword">extends</span> <span class="title">HttpServlet</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 剩余票数</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> count = <span class="number">10</span>;</span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">doPost</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException </span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">doGet</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 创建线程锁对象,用于作为标记</span></span><br><span class="line">        Object ob = <span class="keyword">new</span> Object();</span><br><span class="line">        <span class="comment">// 这个地方写什么对象都行,别瞎传递就行!</span></span><br><span class="line">        <span class="keyword">synchronized</span> (ob) &#123;</span><br><span class="line">            <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;恭喜你,有票&quot;</span>);</span><br><span class="line">                System.out.println(<span class="string">&quot;正在出票&quot;</span>);</span><br><span class="line">                count--;</span><br><span class="line">                System.out.println(<span class="string">&quot;出票完成,剩余票数:&quot;</span> + count);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;很遗憾,没票了!&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JavaWeb笔记06</title>
      <link href="java/JavaWeb/note-request/"/>
      <url>java/JavaWeb/note-request/</url>
      
        <content type="html"><![CDATA[<h2 id="请求的转发"><a href="#请求的转发" class="headerlink" title="请求的转发"></a>请求的转发</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>一个web组件 将未处理完毕的的请求,通过tomcat转交给另一个web组件处理</p><h3 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h3><ol><li>获取请求转发器<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">RequestDispatcher rd = request.getRequestDispatcher(<span class="string">&quot;转发的地址)</span></span><br></pre></td></tr></table></figure></li><li>通过转发器 发起转发<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rd.forward(request,response)</span><br></pre></td></tr></table></figure><h3 id="转发流程"><a href="#转发流程" class="headerlink" title="转发流程"></a>转发流程</h3>步骤1: 范文<h3 id="特点"><a href="#特点" class="headerlink" title="特点:"></a>特点:</h3></li><li>转发过程中,多个servlet之间共享一份请求信息,共享一个响应对象</li><li>转发只能发生在同一个服务器中(转发无法实现跨域)</li><li>无论转发发生多少次,对于浏览器来说,只发起过一次请求,并且只接到了一次响应</li><li>相对于重定向来说,效率更高<h2 id="请求的重新定向"><a href="#请求的重新定向" class="headerlink" title="请求的重新定向"></a>请求的重新定向</h2><h3 id="概念-1"><a href="#概念-1" class="headerlink" title="概念"></a>概念</h3>响应时,告知浏览器新的请求地址,浏览器接收到自动请求新的地址<br>比如你在京東中登录后,会直接重定向到首页中,不用你点击了<h3 id="步骤-1"><a href="#步骤-1" class="headerlink" title="步骤"></a>步骤</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">response.sendRedirect(<span class="string">&quot;重定向地址&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h3>步骤1: 当浏览器<h3 id="特点-1"><a href="#特点-1" class="headerlink" title="特点"></a>特点</h3></li><li>重定向会产生新的请求和新的响应</li><li>使用重定向,可以在多个服务器之间发生(可以实现跨域操作)</li><li>浏览器地址栏的内容,会发生改变</li><li>相对于请求转发而言,效率较低</li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据分析之Excel笔记</title>
      <link href="python/data_analysis/excel/"/>
      <url>python/data_analysis/excel/</url>
      
        <content type="html"><![CDATA[<h2 id="Excel2016应用快速入门"><a href="#Excel2016应用快速入门" class="headerlink" title="Excel2016应用快速入门"></a>Excel2016应用快速入门</h2><h2 id="表格数据的录入与编辑"><a href="#表格数据的录入与编辑" class="headerlink" title="表格数据的录入与编辑"></a>表格数据的录入与编辑</h2><h2 id="设置工作表"><a href="#设置工作表" class="headerlink" title="设置工作表"></a>设置工作表</h2><h2 id="查阅与打印报表"><a href="#查阅与打印报表" class="headerlink" title="查阅与打印报表"></a>查阅与打印报表</h2><h2 id="数据的保存"><a href="#数据的保存" class="headerlink" title="数据的保存"></a>数据的保存</h2><h2 id="公式的基础应用"><a href="#公式的基础应用" class="headerlink" title="公式的基础应用"></a>公式的基础应用</h2><h2 id="公式计算的高级应用"><a href="#公式计算的高级应用" class="headerlink" title="公式计算的高级应用"></a>公式计算的高级应用</h2><h2 id="函数的基础应用"><a href="#函数的基础应用" class="headerlink" title="函数的基础应用"></a>函数的基础应用</h2><h3 id="使用average函数求一组数字的平均值"><a href="#使用average函数求一组数字的平均值" class="headerlink" title="使用average函数求一组数字的平均值"></a>使用average函数求一组数字的平均值</h3><h3 id="侧重库"><a href="#侧重库" class="headerlink" title="侧重库"></a>侧重库</h3><p>pandas: 数据预处理和数据分析库<br>numpy: 数值计算库<br>matplotlib: 绘图库,数据可视化<br>scikit-learn: 机器学习库</p><h4 id="掌握Python基础语法即可"><a href="#掌握Python基础语法即可" class="headerlink" title="掌握Python基础语法即可"></a>掌握Python基础语法即可</h4><h4 id="其他问题"><a href="#其他问题" class="headerlink" title="其他问题"></a>其他问题</h4><p>我数学不好能不能学?<br>我英语不好能不能学?</p><p>数据方向,多读书,多去挖掘什么样的东西跟什么样的东西有关</p><h3 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h3><p>我们以前是用pycharm,现在不用了<br>用Jupyter,推荐环境用anaconda<br>对于科学计算的一个python发行版本(软件)</p><h3 id="初始pandas"><a href="#初始pandas" class="headerlink" title="初始pandas"></a>初始pandas</h3><ul><li>均值</li><li>中位数</li><li>极差</li><li>中程数</li></ul><h3 id="各种图"><a href="#各种图" class="headerlink" title="各种图"></a>各种图</h3><ul><li>条形图</li><li>柱状图</li><li>折线图</li><li>饼状图</li><li>箱线图</li><li>直方图:代表了一种数据的分布情况</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> data_analysis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JavaWeb笔记04</title>
      <link href="java/JavaWeb/note-encoding/"/>
      <url>java/JavaWeb/note-encoding/</url>
      
        <content type="html"><![CDATA[<h2 id="解决GET与POST乱码问题"><a href="#解决GET与POST乱码问题" class="headerlink" title="解决GET与POST乱码问题:"></a>解决GET与POST乱码问题:</h2><h3 id="请求的乱码问题"><a href="#请求的乱码问题" class="headerlink" title="请求的乱码问题"></a>请求的乱码问题</h3><ul><li>GET:tomcat8版本之前,get请求会乱码<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">正常文字 --&gt; UTF-8编码 --&gt; 字节数组 --&gt; ISO-8859-1 编码 --&gt; 乱码文字</span><br><span class="line">正常文字 &lt;-- UTF-8编码 &lt;-- 字节数组 &lt;-- ISO-8859-1 编码 &lt;-- 乱码文字</span><br></pre></td></tr></table></figure></li><li>解决乱码的两种格式:<ul><li>格式1:可用于tomcat8版本之前的GET请求编码 以及 所有版本的POST请求乱码:<br>解决方案: 将乱码的文字,按照乱码的编码ISO-8859-1转换为字节数组,在按照正常的白马UTF-8组装为文字;</li><li>格式2:格式1,解决乱码适用于参数较少的情况,如果参数过多,解决起来极其麻烦<br>tomcat为我们提供了设置请求体编码的方式:<br>注意: 只有POST请求,才有请求体<br>格式:<code>request.setCharacterEncoding(&quot;UTF-8);</code></li></ul></li><li>注意:<ul><li>解决请求乱码的代码,必须运行在获取参数之前<code>request.setCharacterEncoding(&quot;&quot;&quot;)</code>    <h3 id="响应的乱码问题"><a href="#响应的乱码问题" class="headerlink" title="响应的乱码问题"></a>响应的乱码问题</h3></li></ul></li><li>方式1:设置网页的内容类型,以及网页的编码格式:<code>response.setContentType(&quot;text/html;charset=utf-8&quot;);</code></li><li>方式2:设置网页的编码格式(因为没有设置网页内容类型为html,所以浏览器根被就不把他当html解析,当然就乱码了)<code>response.setCharacterEncoding(&quot;UTF-8&quot;);</code></li></ul><h3 id="作业"><a href="#作业" class="headerlink" title="作业:"></a>作业:</h3><ol><li>编写注册页面<ul><li>要求:连接数据库,将表单的数据提交到servlet,在通过servlet将数据插入到数据库user29表格中</li></ul></li><li>编写登录页面<ul><li>要求: 连接数据库,将表单的数据与user29表格中数据对比,匹配提示登录成功,否则提示登录失败</li></ul></li><li>编写修改密码页面<ul><li>要求: 连接数据库,将表单的数据提交到servlet,在通过servlet修改数据库中user29表格的数据</li></ul></li><li>编写主页:<ul><li>要求: 查询数据库user29表格,将表格中所有数据,展示到浏览器中      </li></ul></li></ol><h3 id="作业实现"><a href="#作业实现" class="headerlink" title="作业实现"></a>作业实现</h3><h4 id="项目地址"><a href="#项目地址" class="headerlink" title="项目地址:"></a>项目地址:</h4><p><a href="https://github.com/victorfengming/xdl_javaweb">https://github.com/victorfengming/xdl_javaweb</a>       </p><h4 id="采用技术"><a href="#采用技术" class="headerlink" title="采用技术:"></a>采用技术:</h4><ul><li>JDBC  + 连接池</li><li>Tomcat  +   Servlet   </li><li>Oracle   </li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JavaWeb笔记03</title>
      <link href="java/JavaWeb/note-servlet/"/>
      <url>java/JavaWeb/note-servlet/</url>
      
        <content type="html"><![CDATA[<h1 id="今日内容"><a href="#今日内容" class="headerlink" title="今日内容"></a>今日内容</h1><ol><li>Servlet</li><li>HTTP协议</li><li>Request</li></ol><h2 id="Servlet"><a href="#Servlet" class="headerlink" title="Servlet"></a>Servlet</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><h3 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h3><h3 id="执行原理"><a href="#执行原理" class="headerlink" title="执行原理"></a>执行原理</h3><h3 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h3><h3 id="Servlet3-0注解配置"><a href="#Servlet3-0注解配置" class="headerlink" title="Servlet3.0注解配置"></a>Servlet3.0注解配置</h3><h3 id="Servlet的体系结构"><a href="#Servlet的体系结构" class="headerlink" title="Servlet的体系结构"></a>Servlet的体系结构</h3><ul><li>Servlet – 接口<ul><li>GenericServlet – 抽象类:将Servlet接口中其他方法做了默认空实现,只将service()方法作为抽象<ul><li>将来定义Servlet类时候,可以继承GenericServlet,实现service()方法即可</li></ul></li><li>HTTPServlet – 抽象类:对http协议的一种封装,简化操作<ol><li>定义类继承httpservlet方法</li><li>腹泻doGet/doPost方法<h3 id="Servlet相关配置"><a href="#Servlet相关配置" class="headerlink" title="Servlet相关配置"></a>Servlet相关配置</h3></li></ol></li></ul></li></ul><ol><li>urlpattern:Servlet访问路径<ul><li>一个Servlet可以定义多个访问路径:<code>@WebServlet(&#123;&quot;/d4&quot;,&quot;/dd4&quot;,&quot;/ddd4&quot;&#125;)</code></li><li>路径定义规则:<ol><li><code>/xxx</code></li><li><code>/xxx/xxx</code></li><li><code>*.do</code>*说白了就是通配符,这里注意前面不要加<code>/</code></li></ol></li></ul></li></ol><h2 id="HTTP"><a href="#HTTP" class="headerlink" title="HTTP:"></a>HTTP:</h2><h3 id="概念-Hyper-Text-Transfer-Protocol-超文本传输协议"><a href="#概念-Hyper-Text-Transfer-Protocol-超文本传输协议" class="headerlink" title="概念:Hyper Text Transfer Protocol 超文本传输协议"></a>概念:Hyper Text Transfer Protocol 超文本传输协议</h3><ul><li>传输协议: 定义了,客户端和服务器端通信时,发送数据的格式</li><li>特点:<ol><li>基于TCP/IP 的高级协议</li><li>默认端口:80</li><li>基于请求/响应模型的:一次请求对应一次响应</li><li>无状态的:每次请求之间相互独立,不能交互数据</li></ol></li><li>历史版本:<ul><li>1.0: 每一次请求响应都会建立新的链接</li><li>1.1: 复用</li></ul></li></ul><h3 id="请求消息数据格式"><a href="#请求消息数据格式" class="headerlink" title="请求消息数据格式:"></a>请求消息数据格式:</h3><ol><li>请求行<ul><li>请求方式 请求url 请求协议/版本 GET/login.html HTTP/1.1</li><li>请求方式:<ul><li>HTTP协议有7种请求方式,常用的有2种<ul><li>GET:<ol><li>请求参数在请求行中,在url后</li><li>请求的url长度有限制的</li><li>不太安全</li></ol></li><li>POST:<ol><li>请求参数在请求体中</li><li>请求的url长度没有限制的</li><li>相对的安全(其实对于有心人来说,都是能看到的)             </li></ol></li></ul></li></ul></li></ul></li><li>请求头(客户端告诉服务器的一些信息,头是固定的,值是不一样的)<ul><li>请求头名称:请求头值  </li><li>常见的请求头:<ol><li>User-Agent: 浏览器告诉服务器,我访问你使用的浏览器版本信息<ul><li>可以在服务端获取该头的信息,解决浏览器的兼容性问题</li></ul></li><li>Referer:<a href="http://localhost/login.html">http://localhost/login.html</a><ul><li>告诉服务器,我(当前的请求)从哪里来?<ul><li>作用:<ol><li>防盗链:</li><li>统计工作    </li></ol></li></ul></li></ul></li></ol></li></ul></li><li>请求空行<ul><li>空行,用于分割POST的请求头和请求体的</li></ul></li><li>请求体(正文)  <ul><li>封装POST请求消息的请求体的      </li><li>get方式的没有请求体的</li><li>post方式的请求体是带了一些参数<code>username=zhangsan</code><h3 id="响应消息数据格式"><a href="#响应消息数据格式" class="headerlink" title="响应消息数据格式:"></a>响应消息数据格式:</h3></li></ul></li></ol><p>登录</p><h4 id="请求和响应的过程"><a href="#请求和响应的过程" class="headerlink" title="请求和响应的过程"></a>请求和响应的过程</h4><ol><li>tomcat服务器会根据请求url的资源路径,创建对应的ServletDemo1对象</li><li>tomcat服务器,会创建request和response对象,request对象中封装请求消息数据</li><li>tomcat将request和response两个对象传递给service方法,并且调用service方法. </li><li>程序员(我们),可以通过request对象获取请求消息数据,通过通过response对象设置响应消息数据</li><li>服务器在给浏览器做出响应之前,会从response对象中拿程序员</li></ol><h3 id="request"><a href="#request" class="headerlink" title="request:"></a>request:</h3><ol><li>request对象和response对象的原理<ol><li>request和response对象是有服务器创建的,我们来使用它们</li><li>request对象是来获取请求消息的response是来设置响应消息</li></ol></li><li>request对象继承体系结构<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ServletRequest -- 接口    </span><br><span class="line">    | 继承</span><br><span class="line">HTTPServletRequest -- 接口</span><br><span class="line">    | 实现</span><br><span class="line">org.apache.catalina.connector.RequestFacade类(tomcat)</span><br></pre></td></tr></table></figure></li><li>request:功能<ol><li>获取请求消息数据<ol><li>获取请求行数据<ul><li>GET/day14/demo1?name=zhangsan HTTP/1.1</li><li>方法:<ol><li>获取请求方式:GET<ul><li>String getMethod();</li></ul></li><li>获取虚拟目录:day14<ul><li>String getContextPath()</li></ul></li><li>获取Servlet路径:/demo1<ul><li>Stirng getServletPath</li></ul></li><li>获取get方式请求参数:name = zhangsan<ul><li>String getQueryString()</li></ul></li><li>获取请求URI:/day14/demo1<ul><li>String getRequestURI()</li><li>StringBuffer getRequestURL():<code>http://loaclhost/day14/demo1</code></li><li>url:统一资源定位符:<code>http://loaclhost/day14/demo1</code>(中华人民共和国)</li><li>uri:统一资源标识符:<code>/day14/demo1</code>(共和国)<br>我现在要说的是,uri比url大,同意吧,就像上面的比喻</li></ul></li><li>获取协议版本:HTTP/1.1<ul><li>String getProtocol()</li></ul></li><li>获取客户机的IP地址<ul><li>String getRemoteAddr()</li></ul></li></ol></li></ul></li><li>获取请求头数据</li><li>获取请求体数据</li></ol></li><li>其他功能    </li></ol></li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> JDBC </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JavaWeb笔记02</title>
      <link href="java/JavaWeb/note-tomcat/"/>
      <url>java/JavaWeb/note-tomcat/</url>
      
        <content type="html"><![CDATA[<h1 id="今日内容"><a href="#今日内容" class="headerlink" title="今日内容"></a>今日内容</h1><ol><li>web相关概念回顾</li><li>web服务器软件:Tomcat</li><li>Servlet入门学习</li></ol><h2 id="web相关概念回顾"><a href="#web相关概念回顾" class="headerlink" title="web相关概念回顾"></a>web相关概念回顾</h2><ol><li>软件架构<ol><li>C/S: 客户端/服务器端</li><li>B/S: 浏览器/服务器端</li></ol></li><li>资源分类<ol><li>静态资源: 所有用户访问后,得到的结果都是一样的,成为静态资源,静态资源可以直接被浏览器解析<ul><li>如:html, css ,JavaScript</li></ul></li><li>动态资源:每个用户访问相同资源后,得到的结果可能不一样.称为动态资源,动态资源被访问后,需要先转换为静态资源,在返回给浏览器<ul><li>如:servlet/jsp,php,asp……</li></ul></li></ol></li><li>网络通信三要素<ol><li>IP: 电子设备(计算机)在网络中的唯一标识.</li><li>端口: 应用程序在计算机中的唯一标识.0-65536,建议不要在1024以下,可能被占用了</li><li>传输协议: 规定了数据通信传输的规则<ol><li>基础协议:<ol><li>tcp:安全协议,三次握手.确认双方都在线的情况下再进行数据传输</li><li>udp::不安全的协议,广播发送,可能会丢失,但是速度快</li></ol></li></ol></li></ol></li></ol><h2 id="web服务器软件"><a href="#web服务器软件" class="headerlink" title="web服务器软件:"></a>web服务器软件:</h2><ul><li>服务器: 安装了服务器软件的计算机</li><li>服务器软件: 接收用户的请求,处理请求,做出响应</li><li>web服务器软件: 接收用户的请求,处理请求,做出响应<ul><li>在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目</li><li>web容器</li></ul></li><li>常见的java相关的web服务器软件:<ul><li>webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的</li><li>webSphere: IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的</li><li>JBOSS: JBOSS公司的,大型的JavaEE服务器,支持所有JavaEE规范,收费的</li><li>Tomcat:Apache基金组织,中小型的JavaEE服务器,仅仅支持少量的JavaEE规范servlet/jsp.开源的,免费的</li></ul></li><li>JavaEE: Java语言在企业级开发中使用的技术规范的总和,一共规定了13项大的规范</li><li>Tomcat: <a href="https://victorfengming.gitee.io/blog/tomcat/">tomcat的配置以及使用</a></li></ul><h2 id="serverlet"><a href="#serverlet" class="headerlink" title="serverlet"></a>serverlet</h2><p> <a href="https://victorfengming.gitee.io/blog/servlet/">servlet的配置以及使用</a>                        </p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> JDBC </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JavaWeb笔记01</title>
      <link href="java/JavaWeb/note-XML/"/>
      <url>java/JavaWeb/note-XML/</url>
      
        <content type="html"><![CDATA[<h1 id="今日内容"><a href="#今日内容" class="headerlink" title="今日内容"></a>今日内容</h1><ol><li>XML<ol><li>概念</li><li>语法</li><li>解析</li></ol></li></ol><h2 id="XML"><a href="#XML" class="headerlink" title="XML:"></a>XML:</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念:"></a>概念:</h3><p>Extensible Markup Language 可扩展标记语言<br>可扩展:标签都是自定义的.<code>&lt;user&gt;&lt;student&gt;</code></p><h3 id="功能"><a href="#功能" class="headerlink" title="功能"></a>功能</h3><h4 id="存储数据"><a href="#存储数据" class="headerlink" title="存储数据"></a>存储数据</h4><ol><li>配置文件</li><li>在网络中传输</li></ol><h3 id="一个故事"><a href="#一个故事" class="headerlink" title="一个故事"></a>一个故事</h3><p>由于浏览器之间的竞争,导致HTML发展的十分不顺利</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">用户:唉,这怎么报错了呢?</span><br><span class="line">浏览器1:我不用写引号就能应用属性.贼强</span><br><span class="line">浏览器2:我不用写结束标签还行,NB吧!</span><br><span class="line">浏览器3:我啥也不用写都行,就写有用的标签</span><br><span class="line">浏览器1&#x2F;2:卧槽,你才是真的NB</span><br><span class="line">程序员:完美!O(∩_∩)O哈哈~,再也不怕写错代码了</span><br><span class="line">W3C:你们太恶心了,不行,这样可不行,我才是老大,我说了算</span><br><span class="line">    我来整个XML,这个就严格了,你随便写就不好使了</span><br></pre></td></tr></table></figure><p>但是XML这个弟弟终究没干过他哥哥html,因为程序员们已经习惯了懒散的写法,没人爱用他</p><p>所以XML就找别人玩去了,这个人就是properties(配置文件)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">XML:properties,你这个存配置信息存的不好,你没法区别不同用户的同类属性</span><br><span class="line">    而我就不一样了,我用标签来存储,还能加上id来区分,NB吧!</span><br><span class="line">properties:算你狠!</span><br></pre></td></tr></table></figure><h3 id="XML与HTML区别"><a href="#XML与HTML区别" class="headerlink" title="XML与HTML区别"></a>XML与HTML区别</h3><ol><li>xml标签都是自定义的,html标签是预定义的</li><li>xml的语法严格,html语法松散</li><li>xml是存储数据的,html是展示数据的</li></ol><h3 id="W3c-万维网联盟"><a href="#W3c-万维网联盟" class="headerlink" title="W3c:万维网联盟"></a>W3c:万维网联盟</h3><p>他创建于1994年，是Web技术领域最具权威和影响力的国际中立性技术标准机构。</p><h3 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h3><h4 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h4><ul><li>XML文档的后缀名 .xml</li><li>XML的第一行不能空行,并且必须定义为文档声明</li><li>XML有且仅有一个根标签</li><li>属性值必须使用引号(单双都可以)引起来</li><li>标签必须正确关闭</li><li>XML标签区分大小写<h4 id="快速入门"><a href="#快速入门" class="headerlink" title="快速入门"></a>快速入门</h4></li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&#x27;1.0&#x27; ?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">users</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">user</span> <span class="attr">id</span>=<span class="string">&#x27;1&#x27;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>张三<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">age</span>&gt;</span>19<span class="tag">&lt;/<span class="name">age</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">gender</span>&gt;</span>male<span class="tag">&lt;/<span class="name">gender</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">user</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">user</span> <span class="attr">id</span>=<span class="string">&#x27;2&#x27;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>李四<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">age</span>&gt;</span>21<span class="tag">&lt;/<span class="name">age</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">gender</span>&gt;</span>female<span class="tag">&lt;/<span class="name">gender</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">user</span>&gt;</span></span><br><span class="line">    </span><br><span class="line"><span class="tag">&lt;/<span class="name">users</span>&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>所有的浏览器都可以解析XML文档,要是没报错就说明写对了</p><p>这个XML文档语法特别严格,就算你第一行空一行再写都不行了</p><h4 id="组成部分"><a href="#组成部分" class="headerlink" title="组成部分"></a>组成部分</h4><ol><li>文档声明<ul><li>格式:<code>&lt;?xml 属性列表 ?&gt;</code></li><li>属性列表:<ul><li>version:版本号(必须属性)</li><li>encoding:编码方式,告知解析引擎,当前文档使用的字符集(编码方式),默认字符集ISO–59(高级的开发工具能够根据你这个行写的啥来更改文件的编码方式,比如IDEA)</li><li>standalone:是否独立<ul><li>取值:<ul><li>yes: 不依赖其他文件</li><li>no: 依赖其他文件</li></ul></li></ul></li></ul></li></ul></li><li>指令(了解): 这个是为了结合css的,因为早期xml是要干掉html的,但是没干过</li></ol><ul><li><code>&lt;?xml-stylesheet type=&quot;text/css&quot; href=&quot;a.css&quot;?&gt;</code></li></ul><ol start="3"><li>标签<ol><li>规则:<ul><li>名称可以包含字母,数字以及其他的字符</li><li>名称不能以数字或者标点符号开始</li><li>名称不能以字母xml(或者XML,Xml等等)开始</li><li>名称不能包含空格<br>可以使用任何字母,没有关键字        </li></ul></li></ol></li><li>属性:<ul><li>id属性值唯一</li></ul></li><li>文本:<ul><li>CDATA区:这里面的内容会被原样展示<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">code</span>&gt;</span></span><br><span class="line">    &lt;![CDATA[</span><br><span class="line">        if (a&lt;b)&#123;&#125;</span><br><span class="line">    ]]&gt;</span><br><span class="line"><span class="tag">&lt;/<span class="name">code</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul></li><li>约束:规定xml文档的书写规则</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">xml作为软件的配置文件</span><br><span class="line">谁编写xml?</span><br><span class="line">用户,软件使用者</span><br><span class="line">谁解析xml?   </span><br><span class="line">软件开发者</span><br><span class="line">这个软件不是你理解的软件,而是半成品软件(框架)</span><br></pre></td></tr></table></figure><ul><li><p>作为框架的使用者(程序猿):</p><ul><li>能够在xml中引入约束文档</li><li>能够简单的独栋约束文档(为什么是简单呢,因为智能的IDE会帮你提示)</li></ul></li><li><p>分类:</p><ol><li>DTD:一种简单的约束技术</li><li>SChema:一种复杂的约束技术</li></ol></li><li><p>DTD:</p><ul><li>引入dtd文档到xml文档中<ul><li>内部dtd:将约束规则定义在xml文档中</li><li>外部dtd:将约束规则定义在外部文件中<ul><li>本地:<!DOCTYPE 根标签名 SYSTEM "dtd文件的位置"></li><li>网络:<!DOCTYPE 根标签名 PUBLIC "dtd文件名字" "dtd文件的位置"></li></ul></li></ul></li></ul></li><li><p>Schema:</p><ul><li>引入:<ol><li>填写xml文档的根元素</li><li>引入xsi前缀. <code>xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</code></li><li>引入xsd文件命名空间 <code>xsi:schemaLocation=&quot;http:www.itcast.cn/xml studnet.xsd&quot;</code></li><li>为每个xsd约束声明一个前缀,作为标识 <code>xmlns=&quot;http://www.itcast.cn/xml&quot;</code><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">students</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.itcast.cn/xml&quot;</span> </span></span><br><span class="line"><span class="tag">    <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span> <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.itcast.cn/xml students.xsd&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol></li></ul></li><li><p>解析:操作xml文档,将文件中你的数据读取到内存中</p><ul><li>操作xml文档<ol><li>解析(读取):将文档中的数据读取到内存中</li><li>写入: 将内存中的数据保存到xml文档中.持久化的存储</li></ol></li><li>解析xml的方式:<ul><li>DOM:将标记语言文档一次性加载进内存,在内存中形成一颗dom树<ul><li>优点:操作方便,可以对文档进行CRUD的所有操作</li><li>缺点:占内存</li></ul></li><li>SAX: 逐行读取,基于事件驱动的<ul><li>优点: 不占内存</li><li>缺点: 只能读取,不能增删改</li></ul></li><li>一般在服务器端,我们用DOM的思想,而在移动端,我们用SAX的思想</li></ul></li><li>xml常见的解析器:<ul><li>JAXP: sun公司提供的解析器,支持dom和sax两种思想,(这种比较垃圾,没人用他)</li><li>DOM4J: 一款非常优秀的解析器</li><li>Jsoup: <ul><li>jsoup 是一款Java 的HTML解析器，可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API，可通过DOM，CSS以及类似于jQuery的操作方法来取出和操作数据。</li><li>本来是java的HTML解析器,由于他特别好用,所以用来解析xml</li></ul></li><li>PULL: Android操作系统内置的解析器,sax方式的.</li></ul></li><li>Jsoup使用:<ul><li>快速入门:<ul><li>步骤:<ol><li>导入jar包</li><li>获取Document对象</li><li>获取对应的标签Element对象</li><li>获取数据</li></ol></li></ul></li><li>代码:<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 2.获取Document对象,根据xml文档获取</span></span><br><span class="line">        <span class="comment">// 2.1 获取student.xml的path</span></span><br><span class="line">        String path = JsoupDemo01.class.getClassLoader().getResource(<span class="string">&quot;student.xml&quot;</span>).getPath();</span><br><span class="line">        <span class="comment">// 2.2 解析xml文档,加载文档进内存,获取dom树,--&gt;Document</span></span><br><span class="line">            Document document = Jsoup.parse(<span class="keyword">new</span> File(path),<span class="string">&quot;utf-8&quot;</span>);</span><br><span class="line">            <span class="comment">//3. 获取元素对象Element</span></span><br><span class="line">        Elements elements = document.getElementsByTag(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">        System.out.println(elements.size());</span><br><span class="line">        <span class="comment">// 3.1 获取第一个name的Element对象</span></span><br><span class="line">        Element element = elements.get(<span class="number">0</span>);</span><br><span class="line">        <span class="comment">// 3.2 获取数据</span></span><br><span class="line">        String name = element.text();</span><br><span class="line">        System.out.println(name);</span><br></pre></td></tr></table></figure></li></ul></li><li>对象的使用:<ul><li>Jsoup: 工具类,可以解析html或xml文档,返回document对象<ul><li>parse:解析html文档或xml文档,返回Document</li><li>parse(File in, String charsetName) : 解析xml或html文件</li><li>parse(String html) : 解析xml或html字符串</li></ul></li><li>Document: 文档对象,代表内存中的DOM树<ul><li>获取Element对象<ul><li>getElementById(String id):根据id属性值来获取唯一的Element对象</li><li>getElementsByTag(String tagName) : 根据标签名称获取元素对象集合</li><li>getElementsByAttribute(String key): 根据属性名称来获取元素对象集合</li><li>getElementsByAttributeValue(String key,String value): 根据属性名称来获取元素对象集合</li></ul></li></ul></li><li>Elements: 元素Element对象的集合.可以当做ArrayList<Element>来使用</li><li>Element: 元素对象<ul><li>获取子元素对象<ul><li>getElementById(String id):根据id属性值获取唯一的element对象</li><li>getElementByTag(String tagName):根据标签名称获取元素对象集合</li><li>getElementByAttribute(String key):根据属性名称获取元素对象集合</li><li>getElementByAttributeValue(String key,String value):根据对应的属性名和属性值获取元素对象集合</li></ul></li><li>获取属性值<ul><li>String attr(String key):根据属性名称获取属性值</li></ul></li><li>获取文本内容<ul><li>String text():获取文本内容</li><li>String html():获取标签的所有内容(包括字标签的字符串内容)</li></ul></li></ul></li><li>Node: 节点对象<ul><li>是Document和Element的父类</li></ul></li></ul></li><li>快捷查询方式:<ol><li>selector:选择器<ul><li>使用的方法:Elements select(String CSSQuery)<ul><li>语法:参考selector类中定义的语法</li></ul></li></ul></li><li>XPath:XPath即为xml路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言<ul><li>使用Jsoup的XPath需要额外导入jar包</li></ul></li></ol></li></ul></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> JDBC </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Scrapy笔记01</title>
      <link href="python/spider/Scrapy/python-scrapy/"/>
      <url>python/spider/Scrapy/python-scrapy/</url>
      
        <content type="html"><![CDATA[<p>Python爬虫框架:Scrapy入门<br>Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架.它使用Twisted这个异步网络库来处理网络通讯,架构清晰,并且包含了各种中间件接口,可以灵活的完成各种需求.个人认为Scrapy是Python世界里面最强大的爬虫框架,没有之一,它比BeautifulSoup更加的完善,BeautifulSoup可以说是轮子,而Scrapy则是车子,不需要你关注太多的细节.Scrapy不仅支持Python2.7,Python3也支持.  </p><p>安装:<br>pip install scrapy -&gt; VC++14.0 Twisted<br>解决方法:离线安装 pip install xxx.whl  </p><p>scrapy bench 如果成功了才代表真的安装成功,别的花里胡哨都没有用  </p><p>Scrapy Engine(引擎): 重中之重,负责  </p><h3 id="Scrapy结构图"><a href="#Scrapy结构图" class="headerlink" title="Scrapy结构图"></a>Scrapy结构图</h3><img alt="" src= "/img/loading.gif" data-lazy-src="https://www.runoob.com/wp-content/uploads/2018/10/8c591d54457bb033812a2b0364011e9c_articlex.png" width="700" height="494">  Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯，信号、数据传递等。  Scheduler(调度器): 它负责接受引擎发送过来的Request请求，并按照一定的方式进行整理排列，入队，当引擎需要时，交还给引擎。  Downloader（下载器）：负责下载Scrapy Engine(引擎)发送的所有Requests请求，并将其获取到的Responses交还给Scrapy Engine(引擎)，由引擎交给Spider来处理，  Spider（爬虫）：它负责处理所有Responses,从中分析提取数据，获取Item字段需要的数据，并将需要跟进的URL提交给引擎，再次进入Scheduler(调度器).  Item Pipeline(管道)：它负责处理Spider中获取到的Item，并进行进行后期处理（详细分析、过滤、存储等）的地方。  Downloader Middlewares（下载中间件）：你可以当作是一个可以自定义扩展下载功能的组件。  Spider Middlewares（Spider中间件）：你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件（比如进入Spider的Responses;和从Spider出去的Requests）      ### Scrapy的运作流程  代码写好，程序开始运行...    1 引擎：Hi！Spider, 你要处理哪一个网站？  2 Spider：老大要我处理xxxx.com。  3 引擎：你把第一个需要处理的URL给我吧。  4 Spider：给你，第一个URL是xxxxxxx.com。  5 引擎：Hi！调度器，我这有request请求你帮我排序入队一下。  6 调度器：好的，正在处理你等一下。  7 引擎：Hi！调度器，把你处理好的request请求给我。  8 调度器：给你，这是我处理好的request  9 引擎：Hi！下载器，你按照老大的下载中间件的设置帮我下载一下这个request请求  10 下载器：好的！给你，这是下载好的东西。（如果失败：sorry，这个request下载失败了。然后引擎告诉调度器，这个request下载失败了，你记录一下，我们待会儿再下载）  11 引擎：Hi！Spider，这是下载好的东西，并且已经按照老大的下载中间件处理过了，你自己处理一下（注意！这儿responses默认是交给def parse()这个函数处理的）  12 Spider：（处理完毕数据之后对于需要跟进的URL），Hi！引擎，我这里有两个结果，这个是我需要跟进的URL，还有这个是我获取到的Item数据。  13 引擎：Hi ！管道 我这儿有个item你帮我处理一下！调度器！这是需要跟进URL你帮我处理下。然后从第四步开始循环，直到获取完老大需要全部信息。  14 管道调度器：好的，现在就做！  注意！只有当调度器中不存在任何request了，整个程序才会停止，（也就是说，对于下载失败的URL，Scrapy也会重新下载。）    ### 制作 Scrapy 爬虫 一共需要4步：  新建项目 (scrapy startproject xxx)：新建一个新的爬虫项目  明确目标 （编写items.py）：明确你想要抓取的目标  制作爬虫 （spiders/xxspider.py）：制作爬虫开始爬取网页  存储内容 （pipelines.py）：设计管道存储爬取内容]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> spider </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>druid.properties文件的配置</title>
      <link href="java/JDBC/druid.properties/"/>
      <url>java/JDBC/druid.properties/</url>
      
        <content type="html"><![CDATA[<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># druid.properties文件的配置</span></span><br><span class="line"><span class="attr">driverClassName</span>=<span class="string">com.mysql.jdbc.Driver</span></span><br><span class="line"><span class="attr">url</span>=<span class="string">jdbc:mysql://127.0.0.1:3306/plan</span></span><br><span class="line"><span class="attr">username</span>=<span class="string">root</span></span><br><span class="line"><span class="attr">password</span>=<span class="string"></span></span><br><span class="line"><span class="comment"># 初始化连接数量</span></span><br><span class="line"><span class="attr">initialSize</span>=<span class="string">5</span></span><br><span class="line"><span class="comment"># 最大连接数</span></span><br><span class="line"><span class="attr">maxActive</span>=<span class="string">10</span></span><br><span class="line"><span class="comment"># 最大超时时间</span></span><br><span class="line"><span class="attr">maxWait</span>=<span class="string">3000</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> JDBC </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JDBC笔记-李伟杰版</title>
      <link href="java/JDBC/note3/"/>
      <url>java/JDBC/note3/</url>
      
        <content type="html"><![CDATA[<body><h1>JDBC 03</h1><p>2019/8/1 9:51:41 </p><hr /><h3>笔记网站</h3><pre><code>全球加速:   http://zaixianke.com北京节点:   http://itdage.cn</code></pre><h3>JDBC 事务 ***</h3><pre><code>在dos命令行操作oracle时 , 执行DML , 需要结束事务 (commit提交 或 rollback回退)在JDBC中, 事务是自动提交的, 每执行一条DML语句, 事务就自动提交一次. <p>我们可以通过JDBC的事务API , 开始事务的手动提交, 将多条DML语句看作一个整体, 要么一起成功, 要么一起失败.<br></code></pre></p><h4>JDBC事务操作格式:</h4><pre><code>注意: 开启事务的手动提交 ,是通过连接对象完成的.         某个数据连接对象的事务开启手动提交后, 这个连接对象的事务需要手动控制.  其他连接对象不受影响.<p>操作方法:<br>    1.  开始事务的手动提交:<br>            conn.setAutoCommit(boolean flag);<br>            参数含义:   true表示自动提交 . false表示手动提交.</p><pre><code>2.  提交事务:        conn.commit();3.  回退事务:        rollback();</code></pre><p></code></pre></p><h4>事务案例:</h4><pre><code>    public class Demo &#123;    public static void main(String[] args) throws Exception &#123;        //1.    加载数据库的驱动        Class.forName(&quot;oracle.jdbc.OracleDriver&quot;);        //2.    获取数据库连接对象        Connection conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@localhost:1521:XE&quot;, &quot;system&quot;, &quot;123&quot;);        //2.1   设置连接对象的事务 为 手动提交        conn.setAutoCommit(false);        //3.    开始描述逻辑        System.out.println(&quot;金刚: 转账中...&quot;);        //3.1   减少金刚账户的余额 500 | 3.1.1   预编译SQL执行环境        PreparedStatement state = conn.prepareStatement(&quot;update user33 set money=500 where id=2&quot;);        //3.1.2 执行SQL语句        boolean success = state.executeUpdate()&gt;0?true:false;        if(success) &#123;            System.out.println(&quot;后台逻辑: 金刚余额减少完毕.&quot;);            if(1==2) &#123;                conn.rollback();                throw new RuntimeException(&quot;后台服务器... 停电了&quot;);            &#125;            //3.2   增加豪杰账户的余额 500             //3.2.1 预编译SQL执行环境            PreparedStatement state2 = conn.prepareStatement(&quot;update user33 set money=600 where id=1&quot;);            //3.2.2 执行SQ语句            boolean success2 = state2.executeUpdate()&gt;0?true:false;            if(success2) &#123;                System.out.println(&quot;后台逻辑: 豪杰余额增加完毕&quot;);                conn.commit();            &#125;            state2.close();        &#125;        state.close();    &#125;&#125;</code></pre><h3>批处理 了解</h3><pre><code>将多条SQL语句 放到一起批量处理.<p>批处理将多次对于数据库的操作次数 , 减少到了一次 ! 提高了大量SQL语句一起执行时的性能.</p><p>使用步骤:</p><pre><code>批处理使用Statement类操作    步骤1.    将一条SQ语句加入到批处理中        statement.addBatch(String sql);    步骤2.    执行批处理中的所有语句        statement.executeBatch();</code></pre><p></code></pre></p><h4>批处理案例:</h4><pre><code>    //1.    加载数据库的驱动    Class.forName(&quot;oracle.jdbc.OracleDriver&quot;);    //2.    获取数据库连接对象    Connection conn = DriverManager.getConnection(&quot;jdbc:oracle:thin:@localhost:1521:XE&quot;,             &quot;system&quot;, &quot;123&quot;);    //3.    创建SQL的执行环境    Statement state = conn.createStatement();    //4.    加入SQL语句 到批处理中    for(int i=0;i&lt;1000;i++) &#123;        state.addBatch(&quot;insert into user33 values(SEQ_USER33_ID.NEXTVAL,'name&quot;+i+&quot;',1000)&quot;);    &#125;    //5.    执行批处理    state.executeBatch();    state.close();    conn.close();    System.out.println(&quot;执行完毕&quot;);</code></pre><h3>连接池 *</h3><h4>概述 熟悉</h4><pre><code>由连接池创建连接, 维护连接 我们需要使用连接时, 从连接池中获取连接. 如果池中存在空闲连接, 则拿去使用. 如果不存在空闲连接, 且池未满 , 则在连接池中创建新的连接使用.如果不存在空闲连接, 且池已满 , 则排队等待空闲连接.</code></pre><h4>Properties 文件 与 类 熟悉</h4><pre><code>properties文件 常用于Java中的配置文件.因为Properties文件 可以快速的 与 Properties类 进行转换.    <p>文件:<br>    注释: #开头表示注释行<br>    键值对: 键与值之间使用等号连接,  多个键值对之间使用换行分割</p><p>如何将一个Properties文件, 转换为java中的Map集合对象:</p><pre><code>步骤:    1.  创建Properties对象        Properties ppt = new Properties();              2.  得到Properties文件的字节输入流        InputStream is = //可以通过new FileInputStream , 也可以通过ClassLoader 等等    3.  将流加载到Properties对象        ppt.load(is);</code></pre><p></code></pre></p><h4>使用步骤: *</h4><pre><code>1.  引入相关的jar文件        -   dbcp    :   连接池的代码        -   poll    :   连接池的依赖库<ol start="2"><li><p>创建一个properties文件, 描述连接池的配置 , 内容如下:<br> #数据库连接地址<br> url=jdbc:oracle:thin:@localhost:1521:XE<br> #数据库驱动地址<br> driverClassName=oracle.jdbc.OracleDriver<br> #数据库帐号<br> username=system<br> #数据库密码<br> password=123</p><p> #扩展配置:<br> #初始化连接池时, 创建的连接数量:<br> initialSize=5<br> #最大允许存在的连接数量<br> maxActive=200<br> #空闲时允许保留的最大连接数量<br> maxIdle=10<br> #空闲时允许保留的最小连接数量<br> minIdle=5<br> #排队等候的超时时间<br> maxWait=20000</p></li><li><p>将properties文件, 转换为Properties对象.<br> Properties ppt = new Properties();<br> ppt.load(文件输入流);</p></li><li><p>通过连接池工厂类(BasicDataSourceFactory) , 创建连接池对象 (一次程序启动, 创建一个连接池就够了.)<br> DataSource ds = BasicDataSourceFactory.createDataSource(ppt);</p></li><li><p>通过连接池对象, 获取池中的连接<br> Connection conn = ds.getConnection();</p></li><li><p> 正常JDBC操作<br></code></pre></p></li></ol><h4>连接池案例:*</h4><pre><code>    //3.    将properties文件 转换为Properties对象    Properties ppt = new Properties();    //4.    加载文件的输入流    InputStream is = Demo.class.getClassLoader().getResourceAsStream(&quot;dbcp.properties&quot;);    //空指针异常    ppt.load(is);    //5.    通过工厂类, 创建连接池    DataSource ds = BasicDataSourceFactory.createDataSource(ppt);    //6.    通过连接池, 获取其中的连接 , 并使用    Connection conn = ds.getConnection();    //正常的JDBC操作    PreparedStatement state = conn.prepareStatement            (&quot;insert into user33 values(seq_user33_id.nextval,'嘿嘿嘿',188)&quot;);    int count = state.executeUpdate();    System.out.println(count&gt;0?&quot;数据插入成功&quot;:&quot;数据插入失败&quot;);</code></pre><h4>DBCPUtil工具类 *</h4><pre><code>public class DBCPUtil &#123;<pre><code>private static DataSource dataSource;static &#123;    //在类加载时, 读取配置文件, 配置连接池    //1.    创建Properites对象    Properties ppt = new Properties();    //2.    读取配置文件,     InputStream is = DBCPUtil.class.getClassLoader().getResourceAsStream(&amp;quot;dbcp.properties&amp;quot;);    //3.    将配置文件 加载到Properties对象中    try &#123;        ppt.load(is);    //4.    通过连接池工厂类, 创建连接池        dataSource = BasicDataSourceFactory.createDataSource(ppt);    &#125; catch (Exception e) &#123;        e.printStackTrace();    &#125;&#125;/** * 用于从连接池中 获取一个连接对象 * @return 连接对象 , 如果获取失败返回null */public static Connection getConnection() &#123;    try &#123;        return dataSource.getConnection();    &#125; catch (Exception e) &#123;        e.printStackTrace();        return null;    &#125;&#125;/** * 用于释放资源 * @param conn  连接对象 * @param state 执行环境 * @param result 结果集 */public static void close(Connection conn , Statement state ,ResultSet result) &#123;    if(result!=null) &#123;        try &#123;            result.close();        &#125; catch (SQLException e) &#123;            e.printStackTrace();        &#125;    &#125;    if(state!=null) &#123;        try &#123;            state.close();        &#125; catch (SQLException e) &#123;            // TODO Auto-generated catch block            e.printStackTrace();        &#125;    &#125;    if(conn!=null) &#123;        try &#123;            conn.close();        &#125; catch (SQLException e) &#123;            // TODO Auto-generated catch block            e.printStackTrace();        &#125;    &#125;&#125;</code></pre><p>}<br></code></pre></p><h3>数据库优化 *</h3><pre><code>1.  在进行表格查询时 , where子句中的条件执行顺序是从左至右 , 清除数据量较大的条件应该放在左边.(特别注意: 笛卡尔积消除条件必须放在最左边)<ol start="2"><li><p> 在进行表格查询时 , 列名列表应避免使用<em>号 ! 数据库在执行查询操作时, 会先将</em>号展开, 转换为所有的列名, 再进行查询.</p></li><li><p> 在进行表格查询时 , 能使用where条件筛选的数据, 应尽量避免使用having子句来筛选. 因为where条件执行在having之前 , 在早期筛选掉大量数据, 可以让程序执行的更顺畅.</p></li><li><p> 在进行多表查询时 , 查询的表顺序是从右至左的. 应把表中数据量最少的表放在查询的最右边.</p></li><li><p> 在进行多表查询时 , 应尽可能的给所有的表添加别名, 能明确的区分有冲突的列.</p></li><li><p> 在使用事务时 ,  应尽量多的commit , 尽量早的commit ! 原因是: 事务在未提交时, 数据库会耗费大量的内存 , 来缓存未提交的SQL结果 !</p></li><li><p> 尽可能多的使用函数 来提高SQL执行的效率. </p></li><li><p> SQL语句编写时, 除字符串以外 , 应使用大写字母 ! 因为SQL语句执行时, 会先将小写字母 转换为 大写字母, 再执行.</p></li><li><p> 应尽可能少的访问数据库 (多次数据访问的结果可能相同, 如果缓存起来 ,可以提高程序的执行效率)</p></li><li><p>在索引列上 , 尽可能避免使用not来判断. not关键字如果判断了索引列 , 会导致此次查询索引失效 , 转而使用全表扫描的方式查询.</p></li><li><p>在索引列上, 不能使用算数运算 , 算数运算也会导致索引列使用, 使用全表扫描的方式进行查询.</p></li><li><p>在查询数据时, 如果需要使用&gt;或&lt;的条件, 应替换为&gt;= 或 &lt;= ! </p><pre><code>原因是&amp;gt;和&amp;lt;符号 , 查询时, 是按照&amp;gt;= 和 &amp;lt;= 进行查询, 然后在撇去=的结果.</code></pre><p></code></pre></p></li></ol></body>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> JDBC </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>java中最强语法--lambda表达式</title>
      <link href="java/javase/java-lambda/"/>
      <url>java/javase/java-lambda/</url>
      
        <content type="html"><![CDATA[<h3 id="lambda表达式"><a href="#lambda表达式" class="headerlink" title="lambda表达式"></a>lambda表达式</h3><p>lambda表达式形式：参数，箭头(-&gt;)以及一个表达式，也可以将操作放在代码块{}中。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">(String first,String second)-&gt;</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(first.length()&gt;second.length()) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span>(first.length()&lt;second.length()) <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">() -&gt; System.out.pringln(<span class="string">&quot;i&quot;</span>);</span><br></pre></td></tr></table></figure><p>对于只有一个抽象方法的接口，需要这种接口的对象时，就可以提供一个lambda表达式。这种接口称为函数式接口。Comparator 就是只有一个方法的接口， 所以可以提供一个lambda 表达式：</p><p>函数式接口中可以包含静态方法（已经实现了的方法），默认方法（default），java.lang.Object里的public方法。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Arrays.sort (words ,</span><br><span class="line">(first , second) -&gt; first.length() - second.length()) ;</span><br></pre></td></tr></table></figure><h3 id="方法引用"><a href="#方法引用" class="headerlink" title="方法引用"></a>方法引用</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Timer t = <span class="keyword">new</span> Timer(<span class="number">1000</span>, event -&gt; System.out.println(event));</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line">Timer t = <span class="keyword">new</span> Timer(<span class="number">1000</span>, System.out::println);</span><br></pre></td></tr></table></figure><p>表达式System.out::println是一个方法引用，等价于前面的lambda表达式。主要有3中形式：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//System.out.println == x-&gt;System.out.println(x)</span></span><br><span class="line">object::instanceMethod</span><br><span class="line"><span class="comment">//Math.pow(x,y) == (x,y)-&gt;Math.pow(x,y)</span></span><br><span class="line">Class::staticMethod</span><br><span class="line"><span class="comment">//String::compareToIgnoreCase == (x,y)-&gt;x.compareToIgnoreCase(y)</span></span><br><span class="line">Class::instanceMethod</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>c3p0-config.xml文件简单说明与备忘</title>
      <link href="java/JDBC/c3p0-config/"/>
      <url>java/JDBC/c3p0-config/</url>
      
        <content type="html"><![CDATA[<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">c3p0-config</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">named-config</span> <span class="attr">name</span>=<span class="string">&quot;mysql&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置数据库用户名 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;user&quot;</span>&gt;</span>root<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置数据库密码 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置数据库链接地址 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;jdbcUrl&quot;</span>&gt;</span>jdbc:mysql://localhost:3306/cdcol?useUnicode=true<span class="symbol">&amp;amp;</span>characterEncoding=UTF-8<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置数据库驱动 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driverClass&quot;</span>&gt;</span>com.mysql.jdbc.Driver<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 数据库连接池一次性向数据库要多少个连接对象 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;acquireIncrement&quot;</span>&gt;</span>20<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 初始化连接数 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;initialPoolSize&quot;</span>&gt;</span>10<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 最小连接数 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;minPoolSize&quot;</span>&gt;</span>5<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--连接池中保留的最大连接数。Default: 15 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;maxPoolSize&quot;</span>&gt;</span>30<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--JDBC的标准参数，用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0，则缓存被关闭。Default:0 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;maxStatements&quot;</span>&gt;</span>0<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;maxStatementsPerConnection&quot;</span>&gt;</span>0<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--c3p0是异步操作的，缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能 通过多线程实现多个操作同时被执行。Default:3 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;numHelperThreads&quot;</span>&gt;</span>3<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--用户修改系统配置参数执行前最多等待300秒。Default: 300 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;propertyCycle&quot;</span>&gt;</span>3<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 获取连接超时设置 默认是一直等待单位毫秒 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;checkoutTimeout&quot;</span>&gt;</span>1000<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--每多少秒检查所有连接池中的空闲连接。Default: 0 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;idleConnectionTestPeriod&quot;</span>&gt;</span>3<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--最大空闲时间,多少秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;maxIdleTime&quot;</span>&gt;</span>10<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--配置连接的生存时间，超过这个时间的连接将由连接池自动断开丢弃掉。当然正在使用的连接不会马上断开，而是等待它close再断开。配置为0的时候则不会对连接的生存时间进行限制。 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;maxIdleTimeExcessConnections&quot;</span>&gt;</span>5<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--两次连接中间隔时间，单位毫秒。Default: 1000 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;acquireRetryDelay&quot;</span>&gt;</span>1000<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--c3p0将建一张名为Test的空表，并使用其自带的查询语句进行测试。如果定义了这个参数那么属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作，它将只供c3p0测试使用。Default: null --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;automaticTestTable&quot;</span>&gt;</span>Test<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 获取connnection时测试是否有效 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;testConnectionOnCheckin&quot;</span>&gt;</span>true<span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">named-config</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">c3p0-config</span>&gt;</span></span><br></pre></td></tr></table></figure><p>注释:以上为c3p0-config.xml文件。一般放在项目scr资源文件下。lib导包需要两个c3p0-0.x.x.jar和依赖包mchange-commons-java-0.X.x.jar</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> JDBC </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JDBC笔记02</title>
      <link href="java/JDBC/note2/"/>
      <url>java/JDBC/note2/</url>
      
        <content type="html"><![CDATA[<h1 id="今日内容"><a href="#今日内容" class="headerlink" title="今日内容"></a>今日内容</h1><ol><li>数据库连接池</li><li>Spring JDBC : JDBC Template</li></ol><h2 id="数据库连接池"><a href="#数据库连接池" class="headerlink" title="数据库连接池"></a>数据库连接池</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念:"></a>概念:</h3><p>其实就是一个容器(集合),存放数据库连接的容器</p><p>当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器</p><h3 id="好处"><a href="#好处" class="headerlink" title="好处:"></a>好处:</h3><ul><li>节约资源</li><li>用户访问高效</li></ul><h3 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h3><ol><li>标准接口:DataSource javax.sql包下的<ul><li>方法:<ul><li>获取连接:getConnection()</li><li>归还连接:Connection.close(). 如果连接对象Connection是从连接池中获取的,那么调用方法,则不会再关闭连接了.而是归还连接</li></ul></li></ul></li><li>一般我们不去实现它,有数据库厂商来实现<ol><li>C3P0: 数据库连接池技术</li><li>Druid: 数据库连接池实现技术,由阿里巴巴提供的(这玩意十分的高效,性能好,全球最好的数据库连接池技术!nb吧)        </li></ol></li></ol><h3 id="C3P0-数据库连接池技术"><a href="#C3P0-数据库连接池技术" class="headerlink" title="C3P0:数据库连接池技术"></a>C3P0:数据库连接池技术</h3><h4 id="步骤"><a href="#步骤" class="headerlink" title="步骤:"></a>步骤:</h4><ol><li>导入jar包(两个)<br>c3p0-0.9.5.2.jar<br>mchange-commons-java-0.1.12.jar<br>不要忘记导入数据库的驱动jar包</li><li>定义配置文件:<ul><li>名称:-c3p0.properties 或者 c3p0-config.xml</li><li>路径:直接将文件放在src目录下即可.</li></ul></li><li>创建核心对象 数据库连接池对象 ComboPooledDataSource</li><li>获取连接:getConnection<h3 id="Druid-数据库连接池实现技术-有阿里巴巴提供的"><a href="#Druid-数据库连接池实现技术-有阿里巴巴提供的" class="headerlink" title="Druid :数据库连接池实现技术,有阿里巴巴提供的"></a>Druid :数据库连接池实现技术,有阿里巴巴提供的</h3><h4 id="步骤-1"><a href="#步骤-1" class="headerlink" title="步骤:"></a>步骤:</h4></li><li>导入jar包 fruid-1.9.9.jar</li><li>定义配置文件:<ul><li>是properties形式的</li><li>可以叫任意名称,可以放在任意目录下</li></ul></li><li>加载配置文件.properties</li><li>获取数据库连接池对象:通过工厂来获取DruidDataSourceFactory</li><li>获取连接:getConnection    </li></ol><h2 id="Spring-JDBC"><a href="#Spring-JDBC" class="headerlink" title="Spring JDBC"></a>Spring JDBC</h2><h3 id="Spring-框架对JDBC的简单封装"><a href="#Spring-框架对JDBC的简单封装" class="headerlink" title="Spring 框架对JDBC的简单封装"></a>Spring 框架对JDBC的简单封装</h3><p>提供了一个JDBCTemplate对象简化JDBC的开发<br>步骤:<br>    1. 导入jar包<br>    2. 创建JdbcTemplate对象,依赖于数据源DataSource<br>        - JdbcTemplate template = new JdbcTemplate(ds);<br>    3. 调用JdbcTemplate的方法来完成CRUD的操作<br>        - update():执行DML语句.增删改语句<br>        - queryForMap(): 查询结果将结果集封装为map集合<br>            - 将列明作为key,将值作为value 将这条记录封装为一个map集合<br>            - 注意:这个方法查询的结果集长度只能是1<br>        - queryForList(): 查询结果将结果集封装为list集合<br>            - 注意:将每一条记录封装为一个Map集合,再讲Map集合装载到List集合中<br>        - query(): 查询结果,将结果封装为JavaBean对象<br>            - query的参数:RowMapper,一般我们使用BeanPropertyRowMapper实现类.<br>            - 以完成数据到JavaBean的自动封装<br>            - <code>new BeanPropertyRowMapper&lt;类型&gt;(类型.class)</code><br>        - queryForObject:查询结果,将结果封装为对象<br>            - 一般用于聚合函数的查询<br>    4. 练习:<br>        - 需求:<br>            1. 修改1号数据的 salary 为 10000<br>            2. 添加一条记录<br>            3. 删除刚才添加的记录<br>            4. 查询id为1的记号,将其封装为Map集合<br>            5. 查询所有记录,将其封装为List<br>            6. 查询所有记录,将其封装为Emp对象的List集合<br>            7. 查询总记录数</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> JDBC </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JDBC笔记01</title>
      <link href="java/JDBC/note1/"/>
      <url>java/JDBC/note1/</url>
      
        <content type="html"><![CDATA[<h3 id="学习目标"><a href="#学习目标" class="headerlink" title="学习目标"></a>学习目标</h3><ul><li><input disabled="" type="checkbox"> 理解<code>JDBC</code>原理</li><li><input disabled="" type="checkbox"> 掌握<code>Connection</code>接口的使用</li><li><input disabled="" type="checkbox"> 掌握<code>Statement</code>接口的使用</li><li><input disabled="" type="checkbox"> 掌握<code>ResultSet</code>接口的使用</li><li><input disabled="" type="checkbox"> 掌握<code>PreparedStatement</code>接口的使用</li><li><input disabled="" type="checkbox"> 掌握<code>Properties</code>类与配置文件的使用</li></ul><h3 id="JDBC-概念"><a href="#JDBC-概念" class="headerlink" title="JDBC 概念"></a>JDBC 概念</h3><p>JDBC  (<code>Java DataBase Connectivity</code>)<br>Java数据库连接技术的简称，提供连接各种常用数据库的能力<br>说白了就是java语言连接数据库</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">有一个程序员,他要写一套程序,但是他不知道公司用什么数据库</span><br><span class="line"></span><br><span class="line">所以,他就得学java连mysql连Oracle,连DB2,</span><br><span class="line">市面上所有的关系型数据库,他都得学习一遍,对吧!</span><br><span class="line"></span><br><span class="line">而我们期望使用统一的一套Java代码可以操作所有的关系型数据库</span><br><span class="line">有一个程序员终于忍不住了,写了个JDBC</span><br><span class="line">JDBC:定义了操作所有关系型数据库的规则(接口)</span><br><span class="line"></span><br><span class="line">这里只是写了接口,但是没有写具体的实现类,那么这个实现类谁写呢</span><br><span class="line"></span><br><span class="line">sun公司说了,每一个数据库的厂商你们自己写实现类</span><br><span class="line">所以每个数据库厂商都写了不同的实现类,不同版本的实现类</span><br><span class="line"></span><br><span class="line">我们给这个实现类起了个名字,叫做数据库驱动</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><code>JDBC</code>本质:其实就是官方(<code>Sun</code>公司)定义的一套操作所有关系型数据库的规则,及接口.<br>各个数据库厂商去实现这套接口,提供数据库驱动<code>jar</code>包.我们可以使用这套接口(<code>JDBC</code>)编程,真正执行的代码是驱动<code>jar</code>包中的实现类.</p><h2 id="JDBC快速入门"><a href="#JDBC快速入门" class="headerlink" title="JDBC快速入门"></a><code>JDBC</code>快速入门</h2><h3 id="步骤"><a href="#步骤" class="headerlink" title="步骤:"></a>步骤:</h3><ol><li>导入驱动<code>jar</code>包<br> 官网<code>mysql</code>驱动<code>jar</code>包下载地址:<a href="http://central.maven.org/maven2/mysql/mysql-connector-java/">mysql/mysql-connector-java</a><ol><li>复制<code>mysql-connector-java-5.1.37.jar</code></li><li>右键–&gt;<code>Add as library</code></li></ol></li><li>注册驱动</li><li>获取数据库的连接对象</li><li>定义<code>sql</code></li><li>获取执行<code>sql</code>语句的对象 <code>statement</code></li><li>执行<code>sql</code>,接收返回结果</li><li>处理结果</li><li>释放资源</li></ol><h3 id="实例代码"><a href="#实例代码" class="headerlink" title="实例代码"></a>实例代码</h3><p>别管能不能看懂,直接我就上一堆代码,然后再解释</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.Connection;</span><br><span class="line"><span class="keyword">import</span> java.sql.DriverManager;</span><br><span class="line"><span class="keyword">import</span> java.sql.Statement;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-07 23:43</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo01</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="comment">// 1. 导入驱动jar包</span></span><br><span class="line">        <span class="comment">// 2.注册驱动</span></span><br><span class="line">        Class.forName(<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>);</span><br><span class="line">        <span class="comment">// 3.获取数据库连接对象</span></span><br><span class="line">        Connection conn = DriverManager.getConnection(<span class="string">&quot;jdbc:mysql://localhost:3306/plan&quot;</span>,<span class="string">&quot;root&quot;</span>,<span class="string">&quot;&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//4. 定义sql</span></span><br><span class="line">        String sql = <span class="string">&quot;use plan&quot;</span>;</span><br><span class="line">        <span class="comment">//5. 获取执行sql语句的对象 statement</span></span><br><span class="line">        Statement stmt = conn.createStatement();</span><br><span class="line">        <span class="comment">//6. 执行sql,接收返回结果</span></span><br><span class="line">        <span class="keyword">int</span> count = stmt.executeUpdate(sql);</span><br><span class="line">        <span class="comment">//7. 处理结果</span></span><br><span class="line">        System.out.println(count);</span><br><span class="line">        <span class="comment">//8. 释放资源</span></span><br><span class="line">        stmt.clearBatch();</span><br><span class="line">        conn.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="详解各个对象"><a href="#详解各个对象" class="headerlink" title="详解各个对象"></a>详解各个对象</h3><h4 id="DriverManager-："><a href="#DriverManager-：" class="headerlink" title="DriverManager ："></a><code>DriverManager</code> ：</h4><p>驱动管理对象,用于管理<code>JDBC</code>驱动, 功能如下:</p><h5 id="1-注册驱动"><a href="#1-注册驱动" class="headerlink" title="1. 注册驱动"></a>1. 注册驱动</h5><ol><li>注册与给定的驱动程序<code>static void registerDriver(Driver driver)</code>  </li><li>写代码使用:  <ol><li><code>Class.forName(&quot;com.mysql.jdbc.Driver&quot;);</code>好像这个类中有一个静态代码块,这里面有现成的代码</li><li>通过查看源码发现:在<code>com.mysql.jdbc.Driver</code>类中存在静态代码块<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> &#123;</span><br><span class="line">         <span class="keyword">try</span> &#123;</span><br><span class="line">             DriverManager.registerDriver(<span class="keyword">new</span> Driver());</span><br><span class="line">         &#125; <span class="keyword">catch</span> (SQLException var1) &#123;</span><br><span class="line">             <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(<span class="string">&quot;Can&#x27;t register driver!&quot;</span>);</span><br><span class="line">         &#125;</span><br><span class="line">     &#125;</span><br></pre></td></tr></table></figure></li></ol></li><li>补充:<ul><li>在<code>mysql-connector-java-5.1.37.jar</code> 的<code>5</code>版本之后 </li><li>有一个文件在<code>mysql-connector-java-5.1.37.jar/META-INF/services/java.sql.Driver</code>里面</li><li>这个文件可以让你省略注册驱动的步骤,好吧!</li></ul></li></ol><h5 id="2-获取数据库连接"><a href="#2-获取数据库连接" class="headerlink" title="2. 获取数据库连接:"></a>2. 获取数据库连接:</h5><p>方法:<code>static Connection getConnection(String url,String user,String password)</code></p><p>参数:<br>    - <code>url</code>:指定连接的路径<br>        - 语法:<code>jdbc:mysql://ip地址(域名):端口号/数据库名称</code><br>        - 例子:<code>jdbc:mysql://localhost:3306/plan</code><br>        - 细节:如果连接的是本机的<code>mysql</code>服务器,并且mysql服务器默认端口是3306,则url可以简写为<code>:jdbc:mysql///数据库名称</code><br>        - 例如:<code>Connection conn = DriverManager.getConnection(&quot;jdbc:mysql:///plan&quot;,&quot;root&quot;,&quot;&quot;);</code><br>    - <code>user</code>:用户名<br>    - <code>password</code>:密码</p><h4 id="Connection-：数据库连接对象-用于连接数据库并传送数据"><a href="#Connection-：数据库连接对象-用于连接数据库并传送数据" class="headerlink" title="Connection ：数据库连接对象,用于连接数据库并传送数据"></a><code>Connection</code> ：数据库连接对象,用于连接数据库并传送数据</h4><h5 id="1-获取执行sql的对象"><a href="#1-获取执行sql的对象" class="headerlink" title="1. 获取执行sql的对象"></a>1. 获取执行<code>sql</code>的对象</h5><ul><li><code>Statement createStatement</code></li><li><code>PreparedStatement prepareStatement(String sql)</code></li></ul><h5 id="2-管理事务"><a href="#2-管理事务" class="headerlink" title="2. 管理事务:"></a>2. 管理事务:</h5><ul><li>开启事务: <code>setAutoCommit(boolean autoCommit)</code>: 调用改方法设置参数为<code>false</code>,就开启事务啦,哈哈</li><li>提交事务: <code>commit()</code></li><li>回滚事务: <code>rollback()</code>    </li></ul><h4 id="Statement-：执行sql的对象-负责执行SQL语句"><a href="#Statement-：执行sql的对象-负责执行SQL语句" class="headerlink" title="Statement ：执行sql的对象,负责执行SQL语句"></a><code>Statement</code> ：执行<code>sql</code>的对象,负责执行<code>SQL</code>语句</h4><h5 id="执行sql"><a href="#执行sql" class="headerlink" title="执行sql"></a>执行<code>sql</code></h5><ul><li><code>boolean execute(String sql)</code> :可以执行任意的<code>sql</code>,可能会返回多个结果!(了解即可)</li><li><code>int executeUpdate(String sql)</code>:        <ul><li>执行<code>DML(insert,update,delete)</code>语句,<code>DDL(create,alter,drop)</code>语句</li><li>这个<code>DDL</code>不经常用,所有在这个地方我们都是用前者的</li><li>返回值: 执行语句后,所影响的行数,我们可以通过这个影响的行数判断DML语句是否执行成功,要是大于0就成功了呗,反之,则失败.</li></ul></li><li><code>ResultSet executeQuery(String sql)</code>: 执行<code>DQL(select)</code>语句</li></ul><h5 id="练习-见附录"><a href="#练习-见附录" class="headerlink" title="练习:见附录"></a>练习:见附录</h5><h4 id="ResultSet：结果集对象-负责保存Statement执行后所产生的查询结果"><a href="#ResultSet：结果集对象-负责保存Statement执行后所产生的查询结果" class="headerlink" title="ResultSet：结果集对象,负责保存Statement执行后所产生的查询结果"></a><code>ResultSet</code>：结果集对象,负责保存Statement执行后所产生的查询结果</h4><h5 id="next"><a href="#next" class="headerlink" title="next():"></a><code>next()</code>:</h5><ul><li>游标向下移动一行</li><li>并且判断当前行是否是最后一行的末尾</li><li>返回<code>boolean</code>,如果有数据返回true,反之亦然!</li></ul><h5 id="getXxx-参数-获取数据"><a href="#getXxx-参数-获取数据" class="headerlink" title="getXxx(参数):获取数据"></a><code>getXxx(参数)</code>:获取数据</h5><ul><li>Xxx:代表数据类型 如:<code>int getInt(), String getString()</code></li><li>参数:<ul><li><code>int</code>: 代表列的编号, 从1开始 如<code>getString(1)</code></li><li><code>String</code>: 代表列名称. 如: <code>getDouble(&quot;balance&quot;)</code></li></ul></li></ul><h5 id="注意"><a href="#注意" class="headerlink" title="- 注意:"></a>- 注意:</h5><p>使用步骤:</p><ol><li>游标向下移动一行</li><li>判断是否有数据</li><li>获取数据</li></ol><h5 id="练习"><a href="#练习" class="headerlink" title="- 练习:"></a>- 练习:</h5><p>定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回.</p><ul><li>定义<code>Emp</code>类 用于封装<code>Emp</code>表数据的<code>JavaBean</code></li><li>定义方法 <code>public List&lt;Emp&gt; findAll()&#123;&#125;</code></li><li>实现方法 <code>select * from emp;</code></li></ul><h4 id="PreparedStatement-执行sql的对象-用于负责执行SQL语句"><a href="#PreparedStatement-执行sql的对象-用于负责执行SQL语句" class="headerlink" title="PreparedStatement : 执行sql的对象,用于负责执行SQL语句"></a><code>PreparedStatement</code> : 执行<code>sql</code>的对象,用于负责执行<code>SQL</code>语句</h4><h5 id="1-SQL注入问题-在拼接sql时-有一些特殊关键字参与字符串的拼接-会造成安全性的问题"><a href="#1-SQL注入问题-在拼接sql时-有一些特殊关键字参与字符串的拼接-会造成安全性的问题" class="headerlink" title="1. SQL注入问题:在拼接sql时,有一些特殊关键字参与字符串的拼接.会造成安全性的问题."></a>1. SQL注入问题:在拼接sql时,有一些特殊关键字参与字符串的拼接.会造成安全性的问题.</h5><ol><li>输入用户名随便,输入密码:<code>a&#39; or &#39;a&#39; = &#39;a</code></li><li>sql:<code>select * from user where username = &#39;victor&#39; and password = &#39;a&#39; or &#39;a&#39; = &#39;a&#39;</code></li></ol><h5 id="2-解决sql注入问题-使用PreparedStatement对象来解决-他是"><a href="#2-解决sql注入问题-使用PreparedStatement对象来解决-他是" class="headerlink" title="2. 解决sql注入问题:使用PreparedStatement对象来解决,他是"></a>2. 解决sql注入问题:使用PreparedStatement对象来解决,他是</h5><h5 id="3-预编译sql-参数使用-作为占位符"><a href="#3-预编译sql-参数使用-作为占位符" class="headerlink" title="3. 预编译sql:参数使用?作为占位符"></a>3. 预编译sql:参数使用?作为占位符</h5><h5 id="4-使用步骤"><a href="#4-使用步骤" class="headerlink" title="4. 使用步骤:"></a>4. 使用步骤:</h5><ol><li>导入驱动包</li></ol><ol start="2"><li>注册驱动</li></ol><ol start="3"><li>获取数据库对象连接</li></ol><ol start="4"><li>定义sql</li></ol><ul><li>注意:sql的参数使用?作为占位符.如:<code>select * from user where username = ? and password = ?;</code></li></ul><ol start="5"><li>获取执行sql语句的对象PreparedStatement Connection.prepareStatement(String sql)</li></ol><ol start="6"><li>给? 赋值:</li></ol><ul><li>方法: setXxx(参数1,参数2)<ul><li>参数1:?的位置编号 从1 开始</li><li>参数2:?的值</li></ul></li></ul><ol start="6"><li>执行sql,接受返回结果,不需要传递sql语句</li></ol><ol start="7"><li>处理结果</li></ol><ol start="8"><li>释放资源</li></ol><h5 id="5-注意-后期都会使用PreparedStatement来完成增删改查的所有操作"><a href="#5-注意-后期都会使用PreparedStatement来完成增删改查的所有操作" class="headerlink" title="5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作"></a>5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作</h5><ol><li>可以防止SQL注入</li><li>效率更高</li></ol><h3 id="抽取JDBC工具类-JdbcUtils-java"><a href="#抽取JDBC工具类-JdbcUtils-java" class="headerlink" title="抽取JDBC工具类 : JdbcUtils.java"></a>抽取JDBC工具类 : <code>JdbcUtils.java</code></h3><h4 id="目的-简化书写"><a href="#目的-简化书写" class="headerlink" title="- 目的 : 简化书写"></a>- 目的 : 简化书写</h4><h4 id="分析"><a href="#分析" class="headerlink" title="- 分析 :"></a>- 分析 :</h4><h5 id="1-注册驱动-1"><a href="#1-注册驱动-1" class="headerlink" title="1. 注册驱动"></a>1. 注册驱动</h5><h5 id="2-抽取一个方法获取连接对象"><a href="#2-抽取一个方法获取连接对象" class="headerlink" title="2. 抽取一个方法获取连接对象"></a>2. 抽取一个方法获取连接对象</h5><p>需求 : 不想传递参数(麻烦),还得保证工具类的通用性.<br>解决 : 配置文件    jdbc.properties</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">url=jdbc:mysql:<span class="comment">///plan</span></span><br><span class="line">user=root</span><br><span class="line">password=</span><br><span class="line">driver=com.mysql.jdbc.Driver</span><br></pre></td></tr></table></figure><h4 id="练习-1"><a href="#练习-1" class="headerlink" title="- 练习:"></a>- 练习:</h4><h5 id="需求"><a href="#需求" class="headerlink" title="- 需求 :"></a>- 需求 :</h5><ul><li>通过键盘录入用户名和密码</li><li>判断用户是否登录成功<ul><li><code>select * from user where username = &quot;and password = &quot;&quot;</code></li><li>如果这个sql有结果,则查询成功,反之失败</li></ul></li></ul><h5 id="步骤-1"><a href="#步骤-1" class="headerlink" title="- 步骤 :"></a>- 步骤 :</h5><p>创建数据库表  user</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> <span class="keyword">user</span>(</span><br><span class="line">    id <span class="type">int</span> <span class="keyword">primary</span> key auto_increment,</span><br><span class="line">    username <span class="type">varchar</span>(<span class="number">32</span>),</span><br><span class="line">    password <span class="type">varchar</span>(<span class="number">32</span>)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>插入数据</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> <span class="keyword">user</span></span><br><span class="line"><span class="keyword">values</span> (<span class="keyword">null</span>,&quot;victor&quot;,&quot;123&quot;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> <span class="keyword">user</span></span><br><span class="line"><span class="keyword">values</span> (<span class="keyword">null</span>,&quot;ttkr&quot;,&quot;1907123&quot;);</span><br></pre></td></tr></table></figure><h3 id="JDBC控制事务"><a href="#JDBC控制事务" class="headerlink" title="JDBC控制事务:"></a>JDBC控制事务:</h3><h4 id="1-事务-一个包含多个步骤的业务操作-如果这个业务操作被事务管理-则这多个步骤要么同事成功-要么同时失败"><a href="#1-事务-一个包含多个步骤的业务操作-如果这个业务操作被事务管理-则这多个步骤要么同事成功-要么同时失败" class="headerlink" title="1. 事务: 一个包含多个步骤的业务操作.如果这个业务操作被事务管理,则这多个步骤要么同事成功,要么同时失败."></a>1. 事务: 一个包含多个步骤的业务操作.如果这个业务操作被事务管理,则这多个步骤要么同事成功,要么同时失败.</h4><h4 id="2-操作"><a href="#2-操作" class="headerlink" title="2. 操作:"></a>2. 操作:</h4><ul><li>开始事务</li><li>提交事务</li><li>回滚事务</li></ul><h4 id="3-使用Connection对象来管理事务"><a href="#3-使用Connection对象来管理事务" class="headerlink" title="3. 使用Connection对象来管理事务"></a>3. 使用Connection对象来管理事务</h4><ul><li>开启事务:setAutoCommit(boolean autoCommit) :调用改方法设置参数为false,即开启事务</li><li>提交事务: commit()</li><li>回滚事务: rollback()<ul><li>catch中回滚事务</li></ul></li></ul><h1 id="附录-源代码"><a href="#附录-源代码" class="headerlink" title="附录(源代码)"></a>附录(源代码)</h1><h3 id="account表-添加一条记录"><a href="#account表-添加一条记录" class="headerlink" title="account表 添加一条记录"></a><code>account</code>表 添加一条记录</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.Connection;</span><br><span class="line"><span class="keyword">import</span> java.sql.DriverManager;</span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"><span class="keyword">import</span> java.sql.Statement;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-08 14:41</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;用于插入数据&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo02</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Statement stmt = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1.注册驱动</span></span><br><span class="line">            <span class="comment">// 这行不写也行</span></span><br><span class="line">            <span class="comment">//  Class.forName(&quot;com.mysql.jdbc.Driver&quot;);</span></span><br><span class="line">            <span class="comment">// 2. 定义sql</span></span><br><span class="line">            <span class="comment">//  String sql = &quot;insert into account values(null,&#x27;ttk&#x27;,6299)&quot;;</span></span><br><span class="line">            String sql = <span class="string">&quot;insert into account values(null,&#x27;yupeng&#x27;,5666)&quot;</span>;</span><br><span class="line">            <span class="comment">// 获取Connection对象</span></span><br><span class="line"></span><br><span class="line">            Connection conn = DriverManager.getConnection(<span class="string">&quot;jdbc:mysql:///plan&quot;</span>, <span class="string">&quot;root&quot;</span>, <span class="string">&quot;&quot;</span>);</span><br><span class="line">            <span class="comment">// 4获取执行sql对象 Statement</span></span><br><span class="line">            stmt = conn.createStatement();</span><br><span class="line">            <span class="comment">// 5 执行sql</span></span><br><span class="line">            <span class="keyword">int</span> count = stmt.executeUpdate(sql);</span><br><span class="line">            <span class="comment">// count影响的行数</span></span><br><span class="line">            <span class="comment">// 6.处理结果</span></span><br><span class="line">            System.out.println(count);</span><br><span class="line">            <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;提交成功&quot;</span>);</span><br><span class="line"></span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;添加失败&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 释放资源</span></span><br><span class="line">            <span class="comment">// 为了避免空指针异常需要判断</span></span><br><span class="line">            <span class="keyword">if</span> (stmt != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    stmt.close();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="account表-删除一条记录"><a href="#account表-删除一条记录" class="headerlink" title="account表 删除一条记录"></a><code>account</code>表 删除一条记录</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.Connection;</span><br><span class="line"><span class="keyword">import</span> java.sql.DriverManager;</span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"><span class="keyword">import</span> java.sql.Statement;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-08 15:35</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;从表中删除记录&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo04</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Connection conn = <span class="keyword">null</span>;</span><br><span class="line">        Statement stmt = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1.注册表</span></span><br><span class="line">            <span class="comment">// 2.获取连接对象</span></span><br><span class="line">            conn = DriverManager.getConnection(<span class="string">&quot;jdbc:mysql:///plan&quot;</span>,<span class="string">&quot;root&quot;</span>,<span class="string">&quot;&quot;</span>);</span><br><span class="line">            <span class="comment">// 3. 定义sql</span></span><br><span class="line">            String sql = <span class="string">&quot;delete from account where id = 4&quot;</span>;</span><br><span class="line">            <span class="comment">// 4.获取执行sql对象</span></span><br><span class="line">            stmt = conn.createStatement();</span><br><span class="line">            <span class="comment">// 5.执行sql</span></span><br><span class="line">            <span class="keyword">int</span> count = stmt.executeUpdate(sql);</span><br><span class="line">            <span class="comment">// 6.处理结果</span></span><br><span class="line">            <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;运行成功&quot;</span>);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;失败了!&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 7. 释放资源</span></span><br><span class="line">            <span class="keyword">if</span> (stmt != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    stmt.close();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="account表-修改一条记录"><a href="#account表-修改一条记录" class="headerlink" title="account表 修改一条记录"></a><code>account</code>表 修改一条记录</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.Connection;</span><br><span class="line"><span class="keyword">import</span> java.sql.DriverManager;</span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"><span class="keyword">import</span> java.sql.Statement;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-08 15:16</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;account表修改记录&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo03</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Connection conn = <span class="keyword">null</span>;</span><br><span class="line">        Statement stmt = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1.注册表</span></span><br><span class="line">            <span class="comment">// 2.获取连接对象</span></span><br><span class="line">            conn = DriverManager.getConnection(<span class="string">&quot;jdbc:mysql:///plan&quot;</span>,<span class="string">&quot;root&quot;</span>,<span class="string">&quot;&quot;</span>);</span><br><span class="line">            <span class="comment">// 3. 定义sql</span></span><br><span class="line">            String sql = <span class="string">&quot;update account set balance = 6060 where id = 2&quot;</span>;</span><br><span class="line">            <span class="comment">// 4.获取执行sql对象</span></span><br><span class="line">            stmt = conn.createStatement();</span><br><span class="line">            <span class="comment">// 5.执行sql</span></span><br><span class="line">            <span class="keyword">int</span> count = stmt.executeUpdate(sql);</span><br><span class="line">            <span class="comment">// 6.处理结果</span></span><br><span class="line">            <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;运行成功&quot;</span>);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;失败了!&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 7. 释放资源</span></span><br><span class="line">            <span class="keyword">if</span> (stmt != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    stmt.close();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="DDl-创建一个表"><a href="#DDl-创建一个表" class="headerlink" title="DDl: 创建一个表"></a><code>DDl</code>: 创建一个表</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.Connection;</span><br><span class="line"><span class="keyword">import</span> java.sql.DriverManager;</span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"><span class="keyword">import</span> java.sql.Statement;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-08 15:40</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;用于创建一个新表&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo05</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Connection conn = <span class="keyword">null</span>;</span><br><span class="line">        Statement stmt = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1.注册表</span></span><br><span class="line">            <span class="comment">// 2.获取连接对象</span></span><br><span class="line">            conn = DriverManager.getConnection(<span class="string">&quot;jdbc:mysql:///plan&quot;</span>,<span class="string">&quot;root&quot;</span>,<span class="string">&quot;&quot;</span>);</span><br><span class="line">            <span class="comment">// 3. 定义sql</span></span><br><span class="line">            String sql = <span class="string">&quot;create table student (id int ,name varchar(20))&quot;</span>;</span><br><span class="line">            <span class="comment">// 4.获取执行sql对象</span></span><br><span class="line">            stmt = conn.createStatement();</span><br><span class="line">            <span class="comment">// 5.执行sql</span></span><br><span class="line">            <span class="keyword">int</span> count = stmt.executeUpdate(sql);</span><br><span class="line">            <span class="comment">// 6.处理结果</span></span><br><span class="line">            <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;运行成功&quot;</span>);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;失败了!&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 7. 释放资源</span></span><br><span class="line">            <span class="keyword">if</span> (stmt != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    stmt.close();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="account表-查询一条记录"><a href="#account表-查询一条记录" class="headerlink" title="account表 查询一条记录"></a><code>account</code>表 查询一条记录</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.*;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-08 16:01</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;查询是重中之重&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo06</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Connection conn = <span class="keyword">null</span>;</span><br><span class="line">        Statement stmt = <span class="keyword">null</span>;</span><br><span class="line">        ResultSet rs = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1.注册表</span></span><br><span class="line">            <span class="comment">// 2.获取连接对象</span></span><br><span class="line">            conn = DriverManager.getConnection(<span class="string">&quot;jdbc:mysql:///plan&quot;</span>, <span class="string">&quot;root&quot;</span>, <span class="string">&quot;&quot;</span>);</span><br><span class="line">            <span class="comment">// 3. 定义sql</span></span><br><span class="line">            String sql = <span class="string">&quot;select * from account&quot;</span>;</span><br><span class="line">            <span class="comment">// 4.获取执行sql对象</span></span><br><span class="line">            stmt = conn.createStatement();</span><br><span class="line">            <span class="comment">// 5.执行sql</span></span><br><span class="line">            rs = stmt.executeQuery(sql);</span><br><span class="line">            <span class="comment">// 6.处理结果</span></span><br><span class="line">            <span class="comment">// 6.1 让游标向下移动一行</span></span><br><span class="line">            <span class="comment">// 循环判断游标是否最后一行末尾</span></span><br><span class="line">            <span class="keyword">while</span> (rs.next()) &#123;</span><br><span class="line">                <span class="comment">//            获取数据</span></span><br><span class="line">                <span class="keyword">int</span> id = rs.getInt(<span class="number">1</span>);</span><br><span class="line">                String name = rs.getString(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">                <span class="keyword">double</span> balance = rs.getDouble(<span class="number">3</span>);</span><br><span class="line">                System.out.println(id + <span class="string">&quot;---&quot;</span> + name + <span class="string">&quot;---&quot;</span> + balance);</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 7. 释放资源</span></span><br><span class="line">            <span class="keyword">if</span> (stmt != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    stmt.close();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="工具类"><a href="#工具类" class="headerlink" title="工具类"></a>工具类</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.FileReader;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.net.URL;</span><br><span class="line"><span class="keyword">import</span> java.sql.*;</span><br><span class="line"><span class="keyword">import</span> java.util.Properties;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.util</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-09 10:40</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;JDBC工具类&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcUtils</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//声明三个成员变量</span></span><br><span class="line">    <span class="comment">// 因为只有静态变量才能被静态代码块所访问,被静态方法所访问</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String url;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String user;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String password;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String driver;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 文件的读取,只需要读取一次即可拿到这些值</span></span><br><span class="line"><span class="comment">     * 我们可以使用静态代码块</span></span><br><span class="line"><span class="comment">     * 因为静态代码块是随着类加载进行加载的</span></span><br><span class="line"><span class="comment">     * 只读取一次</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="comment">// 读取资源文件,获取值</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1. 创建 Properties集合类</span></span><br><span class="line">            Properties pro = <span class="keyword">new</span> Properties();</span><br><span class="line">            <span class="comment">// 2.加载文件</span></span><br><span class="line"><span class="comment">//            pro.load(new FileReader(&quot;D:\\IdeaProjects\\itcast\\day04-JDBC\\src\\jdbc.properties&quot;));</span></span><br><span class="line">            <span class="comment">// 这么写指定不行</span></span><br><span class="line">            <span class="comment">// 获取src路径下的文件的方式--&gt;ClassLoader 类加载器</span></span><br><span class="line">            ClassLoader classLoader = JdbcUtils.class.getClassLoader();</span><br><span class="line">            <span class="comment">// 这里的相对路径就是src</span></span><br><span class="line">            URL res = classLoader.getResource(<span class="string">&quot;jdbc.properties&quot;</span>);</span><br><span class="line">            <span class="comment">// 这里URL表示统一资源对应符</span></span><br><span class="line">            String path = res.getPath();</span><br><span class="line"><span class="comment">//            System.out.println(path);</span></span><br><span class="line">            pro.load(<span class="keyword">new</span> FileReader(path));</span><br><span class="line">            <span class="comment">// 3.获取属性,赋值</span></span><br><span class="line">            url = pro.getProperty(<span class="string">&quot;url&quot;</span>);</span><br><span class="line">            user = pro.getProperty(<span class="string">&quot;user&quot;</span>);</span><br><span class="line">            password = pro.getProperty(<span class="string">&quot;password&quot;</span>);</span><br><span class="line">            driver = pro.getProperty(<span class="string">&quot;driver&quot;</span>);</span><br><span class="line">            <span class="comment">// 4. 注册驱动</span></span><br><span class="line">            Class.forName(driver);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (ClassNotFoundException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取连接</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 连接对象</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="comment">//    public static Connection getConnection(String url,String user,String password,String driver) throws SQLException &#123;</span></span><br><span class="line"><span class="comment">//        return DriverManager.getConnection(url, user, password);</span></span><br><span class="line"><span class="comment">//    &#125;</span></span><br><span class="line"><span class="comment">//    这个地方,我既不想用传递参数的方式,还想要简化书写,这可咋整,我们这里使用配置文件的方式,所以要这样写</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Connection <span class="title">getConnection</span><span class="params">()</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> DriverManager.getConnection(url, user, password);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 释放资源方法</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">close</span><span class="params">(Statement stmt, Connection conn)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (stmt != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                stmt.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (conn != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                conn.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 释放资源方法重载</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">close</span><span class="params">(ResultSet rs, Statement stmt, Connection conn)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (rs != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                rs.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (stmt != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                stmt.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (conn != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                conn.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="查询emp表的数据将其封装为对象"><a href="#查询emp表的数据将其封装为对象" class="headerlink" title="查询emp表的数据将其封装为对象"></a>查询emp表的数据将其封装为对象</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> cn.itcast.domain.Emp;</span><br><span class="line"><span class="keyword">import</span> cn.itcast.util.JdbcUtils;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.*;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-08 23:38</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo08</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        List&lt;Emp&gt; list = <span class="keyword">new</span> JdbcDemo08().findAll2();</span><br><span class="line">        <span class="keyword">for</span> (Emp emp : list) &#123;</span><br><span class="line">            System.out.println(emp);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询所有emp对象</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Emp&gt; <span class="title">findAll</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">//提前声明一些变量,以便于能够在try和catch中来回穿梭</span></span><br><span class="line">        Connection conn = <span class="keyword">null</span>;</span><br><span class="line">        Statement stmt = <span class="keyword">null</span>;</span><br><span class="line">        ResultSet rs = <span class="keyword">null</span>;</span><br><span class="line">        List&lt;Emp&gt; list = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1.注册,为了能够兼容mysql5以下的版本,所以写上</span></span><br><span class="line">            Class.forName(<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>);</span><br><span class="line">            <span class="comment">// 2.获取连接</span></span><br><span class="line">            conn = DriverManager.getConnection(<span class="string">&quot;jdbc:mysql:///plan&quot;</span>, <span class="string">&quot;root&quot;</span>, <span class="string">&quot;&quot;</span>);</span><br><span class="line">            <span class="comment">// 3.定义sql</span></span><br><span class="line">            String sql = <span class="string">&quot;select * from emp&quot;</span>;</span><br><span class="line">            <span class="comment">// 4. 获取执行sql的对象</span></span><br><span class="line">            stmt = conn.createStatement();</span><br><span class="line">            <span class="comment">// 5.执行sql</span></span><br><span class="line">            rs = stmt.executeQuery(sql);</span><br><span class="line">            <span class="comment">// 先创建一个引用就ok</span></span><br><span class="line">            Emp emp = <span class="keyword">null</span>;</span><br><span class="line">            list = <span class="keyword">new</span> ArrayList&lt;Emp&gt;();</span><br><span class="line">            <span class="comment">// 6.遍历结果集</span></span><br><span class="line">            <span class="keyword">while</span> (rs.next()) &#123;</span><br><span class="line">                <span class="comment">// 7.获取数据</span></span><br><span class="line">                <span class="keyword">int</span> id = rs.getInt(<span class="string">&quot;id&quot;</span>);</span><br><span class="line">                String ename = rs.getString(<span class="string">&quot;ename&quot;</span>);</span><br><span class="line">                <span class="keyword">int</span> job_id = rs.getInt(<span class="string">&quot;job_id&quot;</span>);</span><br><span class="line">                <span class="keyword">int</span> mgr = rs.getInt(<span class="string">&quot;mgr&quot;</span>);</span><br><span class="line">                <span class="comment">// 这个sqlDate是Date 的子类,所以是可以直接进行赋值的</span></span><br><span class="line">                Date joindate = rs.getDate(<span class="string">&quot;joindate&quot;</span>);</span><br><span class="line">                <span class="keyword">double</span> bonus = rs.getDouble(<span class="string">&quot;bonus&quot;</span>);</span><br><span class="line">                <span class="keyword">double</span> salary = rs.getDouble(<span class="string">&quot;salary&quot;</span>);</span><br><span class="line">                <span class="keyword">int</span> dept_id = rs.getInt(<span class="string">&quot;dept_id&quot;</span>);</span><br><span class="line">                <span class="comment">// 创建emp对象</span></span><br><span class="line">                emp = <span class="keyword">new</span> Emp();</span><br><span class="line">                emp.setId(id);</span><br><span class="line">                emp.setEname(ename);</span><br><span class="line">                emp.setJob_id(job_id);</span><br><span class="line">                emp.setMgr(mgr);</span><br><span class="line">                emp.setJoindate(joindate);</span><br><span class="line">                emp.setBonus(bonus);</span><br><span class="line">                emp.setSalary(salary);</span><br><span class="line">                emp.setDept_id(dept_id);</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 装载集合</span></span><br><span class="line">                list.add(emp);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 7. 释放资源</span></span><br><span class="line">            <span class="keyword">if</span> (stmt != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    stmt.close();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (rs != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    rs.close();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (conn != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    conn.close();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line">    &#125;  <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 演示JDBC工具类</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Emp&gt; <span class="title">findAll2</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">//提前声明一些变量,以便于能够在try和catch中来回穿梭</span></span><br><span class="line">        Connection conn = <span class="keyword">null</span>;</span><br><span class="line">        Statement stmt = <span class="keyword">null</span>;</span><br><span class="line">        ResultSet rs = <span class="keyword">null</span>;</span><br><span class="line">        List&lt;Emp&gt; list = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1.注册,为了能够兼容mysql5以下的版本,所以写上</span></span><br><span class="line">            <span class="comment">// 2.获取连接</span></span><br><span class="line">            conn = JdbcUtils.getConnection();</span><br><span class="line">            <span class="comment">// 3.定义sql</span></span><br><span class="line">            String sql = <span class="string">&quot;select * from emp&quot;</span>;</span><br><span class="line">            <span class="comment">// 4. 获取执行sql的对象</span></span><br><span class="line">            stmt = conn.createStatement();</span><br><span class="line">            <span class="comment">// 5.执行sql</span></span><br><span class="line">            rs = stmt.executeQuery(sql);</span><br><span class="line">            <span class="comment">// 先创建一个引用就ok</span></span><br><span class="line">            Emp emp = <span class="keyword">null</span>;</span><br><span class="line">            list = <span class="keyword">new</span> ArrayList&lt;Emp&gt;();</span><br><span class="line">            <span class="comment">// 6.遍历结果集</span></span><br><span class="line">            <span class="keyword">while</span> (rs.next()) &#123;</span><br><span class="line">                <span class="comment">// 7.获取数据</span></span><br><span class="line">                <span class="keyword">int</span> id = rs.getInt(<span class="string">&quot;id&quot;</span>);</span><br><span class="line">                String ename = rs.getString(<span class="string">&quot;ename&quot;</span>);</span><br><span class="line">                <span class="keyword">int</span> job_id = rs.getInt(<span class="string">&quot;job_id&quot;</span>);</span><br><span class="line">                <span class="keyword">int</span> mgr = rs.getInt(<span class="string">&quot;mgr&quot;</span>);</span><br><span class="line">                <span class="comment">// 这个sqlDate是Date 的子类,所以是可以直接进行赋值的</span></span><br><span class="line">                Date joindate = rs.getDate(<span class="string">&quot;joindate&quot;</span>);</span><br><span class="line">                <span class="keyword">double</span> bonus = rs.getDouble(<span class="string">&quot;bonus&quot;</span>);</span><br><span class="line">                <span class="keyword">double</span> salary = rs.getDouble(<span class="string">&quot;salary&quot;</span>);</span><br><span class="line">                <span class="keyword">int</span> dept_id = rs.getInt(<span class="string">&quot;dept_id&quot;</span>);</span><br><span class="line">                <span class="comment">// 创建emp对象</span></span><br><span class="line">                emp = <span class="keyword">new</span> Emp();</span><br><span class="line">                emp.setId(id);</span><br><span class="line">                emp.setEname(ename);</span><br><span class="line">                emp.setJob_id(job_id);</span><br><span class="line">                emp.setMgr(mgr);</span><br><span class="line">                emp.setJoindate(joindate);</span><br><span class="line">                emp.setBonus(bonus);</span><br><span class="line">                emp.setSalary(salary);</span><br><span class="line">                emp.setDept_id(dept_id);</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 装载集合</span></span><br><span class="line">                list.add(emp);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 7. 释放资源</span></span><br><span class="line">            JdbcUtils.close(rs,stmt,conn);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="用户登录案例"><a href="#用户登录案例" class="headerlink" title="用户登录案例"></a>用户登录案例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> cn.itcast.util.JdbcUtils;</span><br><span class="line"><span class="keyword">import</span> cn.itcast.util.python;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.*;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-09 11:52</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;- 需求 :</span></span><br><span class="line"><span class="comment"> * - 通过键盘录入用户名和密码</span></span><br><span class="line"><span class="comment"> * - 判断用户是否登录成功&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo09</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 1.键盘录入,接收用户名和密码</span></span><br><span class="line">        String username = python.input(<span class="string">&quot;请输入用户名:&quot;</span>);</span><br><span class="line">        String password = python.input(<span class="string">&quot;请输入密码:&quot;</span>);</span><br><span class="line">        <span class="comment">// 2.调用用方法</span></span><br><span class="line">        <span class="comment">//创建对象</span></span><br><span class="line">        <span class="keyword">boolean</span> flag = <span class="keyword">new</span> JdbcDemo09().login(username, password);</span><br><span class="line">        <span class="comment">// 3.判断结果,输出不同语句</span></span><br><span class="line">        <span class="keyword">if</span> (flag) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;登录成功&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;用户名或者密码错误&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 登录方法</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">login</span><span class="params">(String username, String password)</span> </span>&#123;</span><br><span class="line">        Connection conn = <span class="keyword">null</span>;</span><br><span class="line">        PreparedStatement pstmt = <span class="keyword">null</span>;</span><br><span class="line">        ResultSet rs = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (username != <span class="keyword">null</span> || password != <span class="keyword">null</span>) &#123;</span><br><span class="line">                ;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 连接数据库判断是否登录成功</span></span><br><span class="line">            <span class="comment">// 1.获取连接</span></span><br><span class="line">            conn = JdbcUtils.getConnection();</span><br><span class="line">            <span class="comment">// 2.定义sql</span></span><br><span class="line">            String sql = <span class="string">&quot;select * from user where username = ? and password = ?&quot;</span>;</span><br><span class="line">            System.out.println(sql);</span><br><span class="line">            <span class="comment">// 3获取执行sql的对象</span></span><br><span class="line">            <span class="comment">// stmt = conn.createStatement();</span></span><br><span class="line">            <span class="comment">// 升级版本的</span></span><br><span class="line">            pstmt = conn.prepareStatement(sql);</span><br><span class="line">            <span class="comment">// 4执行查询</span></span><br><span class="line">            <span class="comment">//  rs = pstmt.executeQuery(sql);</span></span><br><span class="line">            <span class="comment">// 这里不需要传递参数了</span></span><br><span class="line">            rs = pstmt.executeQuery();</span><br><span class="line">            <span class="comment">// 5判断</span></span><br><span class="line">            <span class="comment">// 要是查到了, 唉, 就直接就返回true</span></span><br><span class="line">            <span class="comment">//            if (rs.next()) &#123;</span></span><br><span class="line">            <span class="comment">//                // 如果有下一行则返回true</span></span><br><span class="line">            <span class="comment">//                return true;</span></span><br><span class="line">            <span class="comment">//            &#125; else &#123;</span></span><br><span class="line">            <span class="comment">//                return false;</span></span><br><span class="line">            <span class="comment">//            &#125;</span></span><br><span class="line">            <span class="comment">// 上面的代码就是垃圾代码</span></span><br><span class="line">            <span class="comment">// 如果有下一行则返回true</span></span><br><span class="line">            <span class="keyword">return</span> rs.next();</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="comment">//        去改配置文件, 数据库要db4</span></span><br><span class="line">            <span class="comment">// 这里就体现了JdbcUtils类的可扩展性很强了,不用改代码都</span></span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 释放资源</span></span><br><span class="line">            JdbcUtils.close(rs,pstmt,conn);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="转账案例"><a href="#转账案例" class="headerlink" title="转账案例"></a>转账案例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.itcast.jdbc;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> cn.itcast.util.JdbcUtils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.Connection;</span><br><span class="line"><span class="keyword">import</span> java.sql.PreparedStatement;</span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> victor</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@site</span> https://victorfengming.gitee.io/</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@company</span> XDL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@project</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> cn.itcast.jdbc</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@created</span> 2019-11-09 14:07</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@function</span> &quot;事务操作&quot;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcDemo10</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        transfer();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 转账函数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">transfer</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        Connection conn = <span class="keyword">null</span>;</span><br><span class="line">        PreparedStatement pstmt1 = <span class="keyword">null</span>;</span><br><span class="line">        PreparedStatement pstmt2 = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 1.获取来接</span></span><br><span class="line">            conn = JdbcUtils.getConnection();</span><br><span class="line">            <span class="comment">// 2. 定义sql</span></span><br><span class="line">            <span class="comment">//2.1 victor+500</span></span><br><span class="line">            String sql1 = <span class="string">&quot;update account set balance = balance + ? where id = ?&quot;</span>;</span><br><span class="line">            <span class="comment">// 2.2 ttkr -50</span></span><br><span class="line">            String sql2 = <span class="string">&quot;update account set balance = balance - ? where id = ?&quot;</span>;</span><br><span class="line">            <span class="comment">// 3.获取执行sql对象</span></span><br><span class="line">            pstmt1 = conn.prepareStatement(sql1);</span><br><span class="line">            pstmt2 = conn.prepareStatement(sql2);</span><br><span class="line">            <span class="comment">// 设置参数</span></span><br><span class="line">            pstmt1.setDouble(<span class="number">1</span>,<span class="number">500</span>);</span><br><span class="line">            pstmt1.setDouble(<span class="number">2</span>,<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">            pstmt2.setDouble(<span class="number">1</span>,<span class="number">500</span>);</span><br><span class="line">            pstmt2.setDouble(<span class="number">2</span>,<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 5.执行sql</span></span><br><span class="line">            pstmt1.executeUpdate();</span><br><span class="line">            <span class="comment">// 手动制造异常</span></span><br><span class="line">            <span class="keyword">int</span> i = <span class="number">3</span>/<span class="number">0</span>;</span><br><span class="line">            pstmt2.executeUpdate();</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            <span class="comment">// 事务回滚</span></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (conn != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    conn.rollback();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException ex) &#123;</span><br><span class="line">                ex.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            JdbcUtils.close(pstmt1,conn);</span><br><span class="line">            JdbcUtils.close(pstmt2,<span class="keyword">null</span>);</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
            <tag> JDBC </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python相关模块安装 </title>
      <link href="python/collection/python-module-install/"/>
      <url>python/collection/python-module-install/</url>
      
        <content type="html"><![CDATA[<div class="post">            <h1 class="postTitle">                <a id="cb_post_title_url" class="postTitle2" href="https://www.cnblogs.com/hellojesson/p/6431398.html">python 相关模块安装 国内镜像地址</a><pre><code>        &lt;/h1&gt;        &lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;        &lt;div class=&quot;postBody&quot;&gt;            </code></pre><div id="cnblogs_post_body" class="blogpost-body ">    <p>python 相关模块安装 国内镜像地址</p><p>pipy国内镜像目前有：</p><p>http://pypi.douban.com/ &nbsp;豆瓣</p><p>http://pypi.hustunique.com/ &nbsp;华中理工大学</p><p>http://pypi.sdutlinux.org/ &nbsp;山东理工大学</p><p>http://pypi.mirrors.ustc.edu.cn/ &nbsp;中国科学技术大学</p><p>https://pypi.tuna.tsinghua.edu.cn/ 清华大学</p><p>对于pip这种在线安装的方式来说，很方便，但网络不稳定的话很要命。使用国内镜像相对好一些，</p><p>&nbsp;</p><p>如果想手动指定源，可以在pip后面跟-i 来指定源，比如用豆瓣的源来安装web.py框架：</p><p>pip install web.py -i http://pypi.douban.com/simple</p><p>注意后面要有/simple目录！！！</p><p>&nbsp;</p><p>要配制成默认的话，需要创建或修改配置文件（linux的文件在~/.pip/pip.conf，windows在%HOMEPATH%\pip\pip.ini），修改内容为：</p><p>code:</p><p>[global]</p><p>index-url = http://pypi.douban.com/simple</p><p>&nbsp;</p><p>推荐使用清华大学的源，速度快(依个人情况而定！)：</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple django</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple pillow</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple paramiko</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple cryptography==1.5.2</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple django-session-security==2.4.0</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple djangorestframework==3.5.3</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple paramiko==2.0.2</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple pycparser==2.16</p><p>pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple PyMySQL==0.7.9</p><p>&nbsp;</p><p>++++++++++++++++++++++++++++++++++++++++++++++++++++++</p><p>Python开发 常用模块安装</p><p>包括Python，eclipse，jdk，pydev，pip，setuptools，beautifulsoup，pyyaml，nltk，mysqldb的下载安装配置。<br>*************************************************<br>python<br>下载：<br>python-2.7.6.amd64.msi<br><a href="http://www.python.org/" rel="external" target="_blank">http://www.python.org/</a><br>Python 2.7.6 released<br>Python 2.7.6 is now available.<br><a href="http://www.python.org/" rel="external" target="_blank">http://www.python.org/</a>download/releases/2.7.6/<br>Windows X86-64 MSI Installer (2.7.6) [1] (sig)<br><br>安装<br>配置：<br>我的电脑-&gt;属性-&gt;高级-&gt;环境变量-&gt;系统变量中的PATH增加:C:\Python27;<br>验证：<br>在桌面建立一个文件pt.py，内容为print 'hello python'<br>在cmd中输入命令python C:\Users\***\Desktop\pt.py<br>***为电脑用户名。<br><br>C:\Users\***&gt;python C:\Users\***\Desktop\pt.py<br>hello python<br>C:\Users\***&gt;<br><br>*************************************************<br>Eclipse：<br>eclipse-java-indigo-SR2-win32-x86_64.zip<br><a href="http://www.eclipse.org/downloads/" rel="external" target="_blank">http://www.eclipse.org/downloads/</a><br>Older Versions<br><a href="http://wiki.eclipse.org/Older_Versions_Of_Eclipse" rel="external" target="_blank">http://wiki.eclipse.org/Older_Versions_Of_Eclipse</a><br>Eclipse Indigo SR2 Packages (v 3.7.2)<br><a href="http://www.eclipse.org/downloads/" rel="external" target="_blank">http://www.eclipse.org/downloads/</a>packages/release/indigo/sr2<br>Eclipse IDE for Java Developers, (128 MB)<br>Downloaded 1,226,421 TimesDetails Windows 32-bit&nbsp;&nbsp;64-bit&nbsp;<br><a href="http://www.eclipse.org/downloads/" rel="external" target="_blank">http://www.eclipse.org/downloads/</a>download.php?file=/technology/epp/downloads/release/indigo/SR2/eclipse-java-indigo-SR2-win32-x86_64.zip<br>Download eclipse-java-indigo-SR2-win32-x86_64.zip from:<br><br>*************************************************<br>jdk：<br>jdk-7u45-windows-x64.exe<br><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" rel="external" target="_blank">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a><br>Windows x64 125.31 MB&nbsp;&nbsp;&nbsp;&nbsp; jdk-7u45-windows-x64.exe<br><a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html" rel="external" target="_blank">http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html</a><br><br>*************************************************<br>pydev<br>为了在Eclipse中进行python工程的开发。<br><a href="http://sourceforge.net/projects/pydev/files/" rel="external" target="_blank">http://sourceforge.net/projects/pydev/files/</a><br>PyDev for Eclipse<br>Looking for the latest version? Download PyDev 3.2.0.zip (8.2 MB)<br>版本一直在更新中，几天前是3.1.0.zip<br>下载完，解压缩，将features和plugins文件夹中的内容分别复制到eclipse的features和plugins文件夹下。<br>重复则替换。<br>具体方法见windows xp，32位，环境下，Eclipse+python平台搭建<br><a href="http://blog.sina.com.cn/s/blog_8af1069601019uaw.html" rel="external" target="_blank">http://blog.sina.com.cn/s/blog_8af1069601019uaw.html</a><br>“安装python插件”，打开eclipse先来配置preference-》PyDev-》Interpreter-Python-》New python的执行exe文件的目录<br><br>*************************************************<br>pip<br><a href="https://pypi.python.org/pypi/pip" rel="external" target="_blank">https://pypi.python.org/pypi/pip</a><br>Download<br>pip-1.4.1.tar.gz<br>A tool for installing and managing Python packages.<br>解压缩，在cmd中进入到pip-1.4.1目录，执行 python setup.py install<br>报错：<br>ImportError: No module named setuptools<br>所以，需要先安装setuptools<br><br>*************************************************<br>setuptools<br><a href="https://pypi.python.org/pypi/setuptools/" rel="external" target="_blank">https://pypi.python.org/pypi/setuptools/</a><br>setuptools 2.0.2<br>点击右侧Downloads按钮，跳至Downloads<br>Scroll to the very bottom of the page to find the links.<br>需要到页面底部去找链接下载。<br>File Type Py Version Uploaded on Size<br>setuptools-2.0.2-py2.py3-none-any.whl (md5)&nbsp;&nbsp;Python Wheel&nbsp;&nbsp;3.4 2013-12-29 527KB<br>setuptools-2.0.2.tar.gz (md5)&nbsp;&nbsp;Source&nbsp;&nbsp;2013-12-29 765KB<br>下载setuptools-2.0.2.tar.gz (md5)<br>解压缩<br>在cmd中进入到setuptools-2.0.2目录，执行 python setup.py install<br>成功标志：<br>Installed c:\python27\lib\site-packages\setuptools-2.0.2-py2.7.egg<br>Processing dependencies for setuptools==2.0.2<br>Finished processing dependencies for setuptools==2.0.2<br>继续安装pip<br><br>*************************************************<br>pip<br>在cmd中进入到pip-1.4.1目录，执行 python setup.py install<br>成功标记：<br>Installed c:\python27\lib\site-packages\pip-1.4.1-py2.7.egg<br>Processing dependencies for pip==1.4.1<br>Finished processing dependencies for pip==1.4.1<br>添加到系统环境变量Path：C:\Python27\Scripts;<br>在cmd测试，输入pip，输出：<br>C:\Users\***&gt;pip<br>Usage:<br>&nbsp;&nbsp;pip [options]<br>Commands:<br>&nbsp;&nbsp;install&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Install packages.<br>&nbsp;&nbsp;uninstall&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uninstall packages.<br>&nbsp;&nbsp;freeze&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Output installed packages in requirements format.<br>&nbsp;&nbsp;list&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List installed packages.<br>&nbsp;&nbsp;show&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Show information about installed packages.<br>&nbsp;&nbsp;search&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Search PyPI for packages.<br>&nbsp;&nbsp;wheel&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Build wheels from your requirements.<br>&nbsp;&nbsp;zip&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Zip individual packages.<br>&nbsp;&nbsp;unzip&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Unzip individual packages.<br>&nbsp;&nbsp;bundle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create pybundles.<br>&nbsp;&nbsp;help&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Show help for commands.<br><br>*************************************************<br>BeautifulSoup<br>可以利用pip进行安装：<br>在cmd中敲入命令查找BeautifulSoup：<br>C:\Users\***&gt;pip search BeautifulSoup<br>BeautifulSoup&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - HTML/XML parser for quick-turnaround applications<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;like screen-scraping.<br>pynliner&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Python CSS-to-inline-styles conversion tool for<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HTML using BeautifulSoup and cssutils<br>Detextile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Convert HTML to Textile syntax using<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeautifulSoup.<br>TreeSoup&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- BeautifulSoup-like wrapper around ElementTree.<br>beautifulscraper&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Python web-scraping library that wraps urllib2 and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeautifulSoup.<br>ElementSoup&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - ElementTree wrapper for BeautifulSoup HTML parser<br>beautifulsoup4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Screen-scraping library<br>collective.soupstrainer&nbsp;&nbsp; - Clean up HTML using BeautifulSoup and filter<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rules.<br>在cmd中敲入命令安装BeautifulSoup<br>C:\Users\***&gt;pip install BeautifulSoup<br>Downloading/unpacking BeautifulSoup<br>&nbsp;&nbsp;Downloading BeautifulSoup-3.2.1.tar.gz<br>&nbsp;&nbsp;Running setup.py egg_info for package BeautifulSoup<br>Installing collected packages: BeautifulSoup<br>&nbsp;&nbsp;Running setup.py install for BeautifulSoup<br>Successfully installed BeautifulSoup<br>Cleaning up...<br>还可参见：安装Beautiful Soup<br><a href="http://blog.sina.com.cn/s/blog_8af1069601019vr2.html" rel="external" target="_blank">http://blog.sina.com.cn/s/blog_8af1069601019vr2.html</a><br><br>*************************************************<br>PyYAML&nbsp;<br>可以利用pip进行安装<br>C:\Users\***&gt;pip search pyyaml<br>PyYAML&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- YAML parser and emitter for Python<br>pyaml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - PyYAML-based module to produce pretty and readable<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;YAML-serialized data<br>yamly&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - pyyaml wrapper<br>enhancedyaml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- It makes it more convenient to use PyYAML.<br>C:\Users\***&gt;pip install PyYAML<br>Downloading/unpacking PyYAML<br>&nbsp;&nbsp;Downloading PyYAML-3.10.tar.gz (241kB): 241kB downloaded<br>&nbsp;&nbsp;Running setup.py egg_info for package PyYAML<br>Installing collected packages: PyYAML<br>&nbsp;&nbsp;Running setup.py install for PyYAML<br>&nbsp;&nbsp;&nbsp;&nbsp;checking if libyaml is compilable<br>&nbsp;&nbsp;&nbsp;&nbsp;Unable to find vcvarsall.bat<br>&nbsp;&nbsp;&nbsp;&nbsp;skipping build_ext<br>Successfully installed PyYAML<br>Cleaning up...<br><br>*************************************************<br>nltk<br><a href="https://pypi.python.org/pypi/nltk/" rel="external" target="_blank">https://pypi.python.org/pypi/nltk/</a><br>nltk 2.0.4<br>File Type Py Version Uploaded on Size<br>nltk-2.0.4.tar.gz (md5)&nbsp;&nbsp;Source&nbsp;&nbsp;2012-11-07 933KB<br>nltk-2.0.4.win32.exe (md5)&nbsp;&nbsp;MS Windows installer&nbsp;&nbsp;2.5 2012-11-07 1MB<br>nltk-2.0.4.zip (md5)&nbsp;&nbsp;Source&nbsp;&nbsp;2012-11-07 1MB<br>下载nltk-2.0.4.tar.gz<br>解压缩，在cmd中进入到nltk-2.0.4目录，执行 python setup.py install<br>成功标志：<br>Installed c:\python27\lib\site-packages\nltk-2.0.4-py2.7.egg<br>Processing dependencies for nltk==2.0.4<br>Searching for PyYAML==3.10<br>Best match: PyYAML 3.10<br>Adding PyYAML 3.10 to easy-install.pth file<br>Using c:\python27\lib\site-packages<br>Finished processing dependencies for nltk==2.0.4<br>打开python Idle：<br>输入import nltk<br>输入nltk.download()<br>出现一个NLTK Downloader对话框，修改Download Diretory（E盘或其他盘符下）。点击all开始下载。<br>下载慢还可以到NLTK Corpora&nbsp;<a href="http://nltk.org/nltk_data/" rel="external" target="_blank">http://nltk.org/nltk_data/</a>手工下载缺失的，然后放到Download Diretory，zip别删。<br>重装系统后nltk_data文件夹可以保留，避免重复下载。<br><br>*************************************************<br>mysqldb<br><a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/" rel="external" target="_blank">http://www.lfd.uci.edu/~gohlke/pythonlibs/</a>#mysql-python<br>MySQL-python-1.2.4.win-amd64-py2.7.exe<br>直接双击安装。<br>成功验证：<br>py文件：<br>import MySQLdb<br>connection = MySQLdb.connect(host="127.0.0.1",user="root",passwd="root",db="dbtest")<br>cursor = connection.cursor()<br>cursor.execute( "Select id,content FROM tabletest&nbsp;&nbsp;")<br>print "Rows selected:", cursor.rowcount<br>运行结果输出dbtest数据库中tabletest表的行数。&nbsp;</p><p>&nbsp;</p></div><div id="MySignature"></div><div class="clear"></div><div id="blog_post_info_block"><pre><code>&lt;div id=&quot;blog_post_info&quot;&gt;</code></pre><div id="green_channel">        <a href="javascript:void(0);" id="green_channel_digg" onclick="DiggIt(6431398,cb_blogId,1);green_channel_success(this,'谢谢推荐！');">好文要顶</a>        <a id="green_channel_follow" onclick="follow('2449c41d-c738-e311-8d02-90b11c0b17d6');" href="javascript:void(0);">关注我</a>    <a id="green_channel_favorite" onclick="AddToWz(cb_entryId);return false;" href="javascript:void(0);">收藏该文</a>    <a id="green_channel_weibo" href="javascript:void(0);" title="分享至新浪微博" onclick="ShareToTsina()"><img src= "/img/loading.gif" data-lazy-src="https://common.cnblogs.com/img/icon_weibo_24.png" alt=""></a>    <a id="green_channel_wechat" href="javascript:void(0);" title="分享至微信" onclick="shareOnWechat()"><img src= "/img/loading.gif" data-lazy-src="https://common.cnblogs.com/img/wechat.png" alt=""></a></div><div id="author_profile">    <div id="author_profile_info" class="author_profile_info">            <a href="https://home.cnblogs.com/u/hellojesson/" target="_blank"><img src= "/img/loading.gif" data-lazy-src="https://pic.cnblogs.com/face/575577/20150707101005.png" class="author_avatar" alt=""></a>        <div id="author_profile_detail" class="author_profile_info">            <a href="https://home.cnblogs.com/u/hellojesson/">hello-Jesson</a><br>            <a href="https://home.cnblogs.com/u/hellojesson/followees/">关注 - 22</a><br>            <a href="https://home.cnblogs.com/u/hellojesson/followers/">粉丝 - 32</a>        </div>    </div>    <div class="clear"></div>    <div id="author_profile_honor"></div>    <div id="author_profile_follow">                <a href="javascript:void(0);" onclick="follow('2449c41d-c738-e311-8d02-90b11c0b17d6');return false;">+加关注</a>    </div></div><div id="div_digg">    <div class="diggit" onclick="votePost(6431398,'Digg')">        <span class="diggnum" id="digg_count">0</span>    </div>    <div class="buryit" onclick="votePost(6431398,'Bury')">        <span class="burynum" id="bury_count">0</span>    </div>    <div class="clear"></div>    <div class="diggword" id="digg_tips">    </div></div><script type="text/javascript">    currentDiggType = 0;</script></div><pre><code>&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div id=&quot;post_next_prev&quot;&gt;&lt;a href=&quot;https://www.cnblogs.com/hellojesson/p/6429024.html&quot; class=&quot;p_n_p_prefix&quot;&gt;« &lt;/a&gt; 上一篇：    &lt;a href=&quot;https://www.cnblogs.com/hellojesson/p/6429024.html&quot; title=&quot;发布于 2017-02-22 15:02&quot;&gt;Celery启动Django项目：Client sent AUTH, but no password is set 错误处理&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.cnblogs.com/hellojesson/p/6432149.html&quot; class=&quot;p_n_p_prefix&quot;&gt;» &lt;/a&gt; 下一篇：    &lt;a href=&quot;https://www.cnblogs.com/hellojesson/p/6432149.html&quot; title=&quot;发布于 2017-02-23 10:09&quot;&gt;数据库默认端口&lt;/a&gt;</code></pre></div></div>            </div>            <div class="postDesc">posted @ <span id="post-date">2017-02-22 22:43</span>&nbsp;<a href="https://www.cnblogs.com/hellojesson/">hello-Jesson</a> 阅读(<span id="post_view_count">7283</span>) 评论(<span id="post_comment_count">0</span>) <a href="https://i.cnblogs.com/EditPosts.aspx?postid=6431398" rel="nofollow"> 编辑</a> <a href="javascript:void(0)" onclick="AddToWz(6431398); return false;">收藏</a></div>        </div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>CS架构的建议聊天室</title>
      <link href="python/GUI/pyqt5/pyqt5-socket/"/>
      <url>python/GUI/pyqt5/pyqt5-socket/</url>
      
        <content type="html"><![CDATA[<h3 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"><span class="comment"># 定义保存所有socket的列表</span></span><br><span class="line">socket_list = []</span><br><span class="line"><span class="comment"># 创建socket对象</span></span><br><span class="line">ss = socket.socket()</span><br><span class="line"><span class="comment"># 将socket绑定到本机IP和端口</span></span><br><span class="line">ss.bind((<span class="string">&#x27;127.0.0.1&#x27;</span>, <span class="number">6666</span>))</span><br><span class="line"><span class="comment"># 服务端开始监听来自客户端的连接</span></span><br><span class="line">ss.listen()</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">read_from_client</span>(<span class="params">s</span>):</span></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="keyword">return</span> s.recv(<span class="number">2048</span>).decode(<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line">    <span class="comment"># 如果捕获到异常，则表明该socket对应的客户端已经关闭</span></span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        <span class="comment"># 删除该socket</span></span><br><span class="line">        socket_list.remove(s)      <span class="comment"># ①</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">server_target</span>(<span class="params">s</span>):</span></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="comment"># 采用循环不断地从socket中读取客户端发送过来的数据</span></span><br><span class="line">        <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">            content = read_from_client(s)</span><br><span class="line">            print(content)</span><br><span class="line">            <span class="keyword">if</span> content <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            <span class="keyword">for</span> client_s <span class="keyword">in</span> socket_list:</span><br><span class="line">                client_s.send(content.encode(<span class="string">&#x27;utf-8&#x27;</span>))</span><br><span class="line">    <span class="keyword">except</span> e:</span><br><span class="line">        print(e.strerror)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        <span class="comment"># 此行代码会阻塞，将一直等待别人的连接</span></span><br><span class="line">        s, addr = ss.accept()</span><br><span class="line">        socket_list.append(s)</span><br><span class="line">        <span class="comment"># 每当客户端连接后启动一个线程为该客户端服务</span></span><br><span class="line">        threading.Thread(target=server_target, args=(s, )).start()</span><br></pre></td></tr></table></figure><h3 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by 秋叶夏风</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;图形化聊天界面主模块&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入python系统类库</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入时间模块,用于获取聊天提示信息</span></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入生成界面类的模块</span></span><br><span class="line"><span class="keyword">from</span> PyQt5 <span class="keyword">import</span> QtCore, QtGui, QtWidgets</span><br><span class="line"><span class="comment"># 导入pyqt5类用到的类库,QApplication应用程序类,Qwidget控件的基类</span></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication, QWidget, QInputDialog</span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入socket模块</span></span><br><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 定义连接类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Connect</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">socket_init</span>(<span class="params">self,ip</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 创建socket对象</span></span><br><span class="line">        self.s = socket.socket()</span><br><span class="line">        <span class="comment"># 连接远程主机</span></span><br><span class="line">        self.s.connect((ip, <span class="number">6666</span>))</span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">read_from_server</span>(<span class="params">s</span>):</span></span><br><span class="line">            <span class="keyword">global</span> message_content</span><br><span class="line">            <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">                mes = s.recv(<span class="number">2048</span>).decode(<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line">                message_content += mes</span><br><span class="line">                print(<span class="string">&quot;message_content---&gt;&quot;</span>,message_content)</span><br><span class="line">                <span class="comment"># main.form.set_label_content()</span></span><br><span class="line">                <span class="comment"># TODO 这里在局部调用了全局的变量</span></span><br><span class="line">                <span class="comment"># TODO 有待优化</span></span><br><span class="line">                form.set_label_content()</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 客户端启动线程不断地读取来自服务器的数据</span></span><br><span class="line">        threading.Thread(target=read_from_server, args=(self.s, )).start()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">input_chat_content</span>(<span class="params">self,line</span>):</span></span><br><span class="line">        <span class="comment"># line = input(&#x27;&#x27;)</span></span><br><span class="line">        <span class="keyword">if</span> line <span class="keyword">is</span> <span class="literal">None</span> <span class="keyword">or</span> line == <span class="string">&#x27;exit&#x27;</span>:</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        <span class="comment"># 将用户的键盘输入内容写入socket</span></span><br><span class="line">        self.s.send(line.encode(<span class="string">&#x27;utf-8&#x27;</span>))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 定义UI类</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Form implementation generated from reading ui file &#x27;Client_fg.ui&#x27;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># Created by: PyQt5 UI code generator 5.13.0</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># WARNING! All changes made in this file will be lost!</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Ui_Form</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># TODO 初始化连接,这里需要改掉,加上用户名验证</span></span><br><span class="line">        self.connect_init()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">showDialog</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.name, ok = QInputDialog.getText(QWidget(), <span class="string">&#x27;用户登陆&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;Enter your name:&#x27;</span>)</span><br><span class="line">        <span class="keyword">if</span> ok:</span><br><span class="line">            print(self.name)</span><br><span class="line">            <span class="comment"># self.le.setText(str(text))</span></span><br><span class="line"></span><br><span class="line">        print(self.name+<span class="string">&quot;哈哈&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 初始化界面</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">setupUi</span>(<span class="params">self, Form</span>):</span></span><br><span class="line">        Form.setObjectName(<span class="string">&quot;Form&quot;</span>)</span><br><span class="line">        Form.resize(<span class="number">528</span>, <span class="number">291</span>)</span><br><span class="line">        self.label = QtWidgets.QLabel(Form)</span><br><span class="line">        self.label.setGeometry(QtCore.QRect(<span class="number">90</span>, <span class="number">40</span>, <span class="number">291</span>, <span class="number">121</span>))</span><br><span class="line">        self.label.setObjectName(<span class="string">&quot;label&quot;</span>)</span><br><span class="line">        self.horizontalLayoutWidget = QtWidgets.QWidget(Form)</span><br><span class="line">        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(<span class="number">30</span>, <span class="number">200</span>, <span class="number">481</span>, <span class="number">80</span>))</span><br><span class="line">        self.horizontalLayoutWidget.setObjectName(<span class="string">&quot;horizontalLayoutWidget&quot;</span>)</span><br><span class="line">        self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)</span><br><span class="line">        self.horizontalLayout.setContentsMargins(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>)</span><br><span class="line">        self.horizontalLayout.setObjectName(<span class="string">&quot;horizontalLayout&quot;</span>)</span><br><span class="line">        self.lineEdit = QtWidgets.QLineEdit(self.horizontalLayoutWidget)</span><br><span class="line">        self.lineEdit.setObjectName(<span class="string">&quot;lineEdit&quot;</span>)</span><br><span class="line">        self.horizontalLayout.addWidget(self.lineEdit)</span><br><span class="line">        self.pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)</span><br><span class="line">        self.pushButton.setObjectName(<span class="string">&quot;pushButton&quot;</span>)</span><br><span class="line">        <span class="comment"># 绑定按钮点击事件</span></span><br><span class="line">        self.pushButton.clicked.connect(self.send_message)</span><br><span class="line">        self.horizontalLayout.addWidget(self.pushButton)</span><br><span class="line"></span><br><span class="line">        self.retranslateUi(Form)</span><br><span class="line">        QtCore.QMetaObject.connectSlotsByName(Form)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">retranslateUi</span>(<span class="params">self, Form</span>):</span></span><br><span class="line">        _translate = QtCore.QCoreApplication.translate</span><br><span class="line">        Form.setWindowTitle(_translate(<span class="string">&quot;Form&quot;</span>, <span class="string">&quot;Form&quot;</span>))</span><br><span class="line">        self.label.setText(_translate(<span class="string">&quot;Form&quot;</span>, <span class="string">&quot;&quot;</span>))</span><br><span class="line">        self.pushButton.setText(_translate(<span class="string">&quot;Form&quot;</span>, <span class="string">&quot;发送&quot;</span>))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">connect_init</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 创建连接对象</span></span><br><span class="line">        self.c = Connect()</span><br><span class="line">        self.c.socket_init(<span class="string">&#x27;127.0.0.1&#x27;</span>)</span><br><span class="line">        <span class="comment"># 测试发送数据</span></span><br><span class="line">        self.c.input_chat_content(<span class="string">&quot;我来冒个泡!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># TODO 这个类中的方法用到了那个模块的</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">send_message</span>(<span class="params">self</span>):</span></span><br><span class="line">        name = <span class="string">&quot;victor&quot;</span></span><br><span class="line">        <span class="comment"># 获取输入框中的内容</span></span><br><span class="line">        con = self.lineEdit.text()</span><br><span class="line">        <span class="comment"># 获取现在时间</span></span><br><span class="line">        t = <span class="built_in">str</span>(time.strftime(<span class="string">&quot;%H:%M:%S&quot;</span>, time.localtime()))</span><br><span class="line">        new_con = <span class="string">&quot;\n&quot;</span> + t + <span class="string">&quot; &quot;</span> + name + <span class="string">&quot;说:&quot;</span> + con</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 发送出去</span></span><br><span class="line">        self.c.input_chat_content(new_con)</span><br><span class="line">        <span class="comment"># self.label.setText(new_con)</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        # 设置本label显示</span></span><br><span class="line"><span class="string">        con = self.lineEdit.text()</span></span><br><span class="line"><span class="string">        # 获取现在时间</span></span><br><span class="line"><span class="string">        t = str(time.strftime(&quot;%H:%M:%S&quot;, time.localtime()))</span></span><br><span class="line"><span class="string">        new_con = self.label.text()+&quot;\n&quot;+t+&quot; &quot;+name+&quot;说:&quot;+con</span></span><br><span class="line"><span class="string">        self.label.setText(new_con)</span></span><br><span class="line"><span class="string">        # print()</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        <span class="comment"># 清空input框</span></span><br><span class="line">        self.lineEdit.setText(<span class="string">&quot;&quot;</span>)</span><br><span class="line"></span><br><span class="line">        print(<span class="string">&quot;--------------&quot;</span>)</span><br><span class="line">        print(message_content)</span><br><span class="line">        print(<span class="string">&quot;--------------&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">set_label_content</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.label.setText(message_content)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    <span class="comment"># TODO 这里的显示内容的当前模块的</span></span><br><span class="line">    <span class="comment"># TODO 在一个模块中的变量所有的类都能用上,要不然就会出现调用的时候还没定义</span></span><br><span class="line">    <span class="comment"># TODO 而且还没有传递引用,传递的是值这就难受了</span></span><br><span class="line"></span><br><span class="line">    message_content = <span class="string">&quot;init_content&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 实例化App对象</span></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 实例化界面基类</span></span><br><span class="line">    w1 = QWidget()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 实例化生成的界面的类</span></span><br><span class="line">    form = Ui_Form()</span><br><span class="line">    <span class="comment"># 先输入服务端ip</span></span><br><span class="line">    <span class="comment"># 将生成的窗体控件及配置载入到w控件对象汇总</span></span><br><span class="line">    form.setupUi(w1)</span><br><span class="line">    form.showDialog()</span><br><span class="line">    <span class="comment"># 使用窗体显示</span></span><br><span class="line">    <span class="comment"># 这里就执行了一次</span></span><br><span class="line">    form.set_label_content()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 显示窗体</span></span><br><span class="line">    w1.show()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 主消息循环</span></span><br><span class="line">    sys.exit(app.exec_())</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> socket </tag>
            
            <tag> PyQt5 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PyQt5学习笔记11-15</title>
      <link href="python/GUI/pyqt5/note/pyqt5-note11-15/"/>
      <url>python/GUI/pyqt5/note/pyqt5-note11-15/</url>
      
        <content type="html"><![CDATA[<h1 id="PyQt5的第十一课-PyQt5三原色案例"><a href="#PyQt5的第十一课-PyQt5三原色案例" class="headerlink" title="PyQt5的第十一课 - PyQt5三原色案例"></a>PyQt5的第十一课 - PyQt5三原色案例</h1><h3 id="知识回顾"><a href="#知识回顾" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>QGridLayout网格式布局</li><li>默认索引从0开始</li><li>QTextEdit多行文本框</li><li>注意:网格布局是可以扩展性的,可以随着系统界面变化而变化的</li></ul><h3 id="案例目标"><a href="#案例目标" class="headerlink" title="案例目标"></a>案例目标</h3><p>制作一个界面如右图.功能是描述三原色.在设计中,我们往往有三原色概念</p><p>基本上所哟的颜色都可以由三种颜色调和而成,这三种颜色分别是RGB</p><p>,我们使用三个按钮分别表示这个三种颜色,每个按钮都可以有哦两种状态</p><p>为蓝色,未选中按钮为默认灰色,在界面中用一个区块(QFrame)来表示颜色</p><h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><ul><li>制作界面采用PyQt5进行布局</li><li>采用合资布局的方法进行界面布局</li><li>按钮的状态功能加入</li><li>设置Qframe的背景颜色</li><li>设置按钮的点击事件</li><li>设置三原色情况,最终还是要通过改变Qframe样式来实现颜色变化</li></ul><h3 id="框架容器QFrame"><a href="#框架容器QFrame" class="headerlink" title="框架容器QFrame"></a>框架容器QFrame</h3><ul><li><p>必须使用类库QFrame</p></li><li><p>初始化:</p></li><li><p>myframe = QFrame()</p></li><li><p>注意点</p></li><li><p>父容器可以采用后期添加到盒子布局的方式进行设置</p></li><li><p>当然可以可以在初始化的时候设置</p></li><li><p>父容器的设置会影响子容器的生命周期的</p></li></ul><h3 id="控件设置CSS风格"><a href="#控件设置CSS风格" class="headerlink" title="控件设置CSS风格"></a>控件设置CSS风格</h3><ul><li><p>可以通过setStyleSheet方法来设置</p></li><li><p>这个方法几乎在所丶有的QWidget的控件之上都能实现</p></li><li><p>使用举例:<br>  myframe.setStyleSheet(“QWidget{background-color:black}”)</p></li><li><p>在setStyleSheet方法中使用CSS类型的字符串</p></li><li><p>这个CSS风格使用格式:</p></li><li><p>需要控制的空阿金标签或者行为,然后写一个大括号{},我们在大括号    内写各类控制某个标签的样式.样式的书写风格就是   <code>属性:值</code></p></li></ul><h3 id="按钮是否选中可以选中与不选中的切换"><a href="#按钮是否选中可以选中与不选中的切换" class="headerlink" title="按钮是否选中可以选中与不选中的切换"></a>按钮是否选中可以选中与不选中的切换</h3><p>使用setChecable方法,默认情况下这个方法设置的值为false,我们设置为True才行</p><h3 id="槽函数传参"><a href="#槽函数传参" class="headerlink" title="槽函数传参"></a>槽函数传参</h3><ul><li>槽函数定义需要看我们的信号源是否有参数</li><li>信号源中有参数的部分的信号参数我们需要使用中括号</li><li>使用举例:<code>btnRed.clicked[bool].connect(self.setColor)</code></li><li>如何传递控件对象?</li><li>使用self.sender()就会返回触发事件对象本身</li></ul><h3 id="三原色函数"><a href="#三原色函数" class="headerlink" title="三原色函数"></a>三原色函数</h3><ul><li><p>使用QColor来实现</p></li><li><p>红,绿,蓝范围在<code>[0,255]</code>之间</p></li><li><p>第1个参数表示红色</p></li><li><p>第2个参数表示绿色</p></li><li><p>第3个参数表示蓝色</p></li></ul><h3 id="总结强调"><a href="#总结强调" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握三原色函数</li><li>掌握布局的思想</li><li>掌握按钮的选择状态</li><li>掌握信号槽传参和控件事件的传递</li></ul><h1 id="PyQt5的第十二课-PyQt5三原色"><a href="#PyQt5的第十二课-PyQt5三原色" class="headerlink" title="PyQt5的第十二课 - PyQt5三原色"></a>PyQt5的第十二课 - PyQt5三原色</h1><h3 id="知识回顾-1"><a href="#知识回顾-1" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>程序中的三原色</li><li>按钮状态的改变Qpushbutton装填的改变,设置是否选重中checked</li><li>利用我们已经学过的布局思想</li></ul><h3 id="qlineEdit使用"><a href="#qlineEdit使用" class="headerlink" title="qlineEdit使用"></a>qlineEdit使用</h3><ul><li>它是一个单行文本框</li><li>事件:文本改变事件.textchange类似这样的代码的事件.</li><li>结合qt中基本的信号槽机制</li><li>注意:信号在传递参数的时候要把小括号改成</li></ul><h3 id="设置标签宽度自适应"><a href="#设置标签宽度自适应" class="headerlink" title="设置标签宽度自适应"></a>设置标签宽度自适应</h3><ul><li>标签使用Qlabel</li><li>使用标签的时候,标签默认的宽度是固定的,当标签文本内容宽度的显示区域的时候</li><li>超出部分的内容就会进行遮挡.此时我们可以考虑让标签的内容积习难改in自定义区域适应</li><li>标签区域自适应适应函数adjustsize</li></ul><h3 id="总结强调-1"><a href="#总结强调-1" class="headerlink" title="总结强调"></a>总结强调</h3><p>掌握qlineEdit的文本改变事件<br>掌握文本标签的区域自适应<br>掌握事件的信号槽关系以及传递参数</p><h1 id="PyQt5的第十三课-PyQt5复选框-QCheckBox控件事件应用"><a href="#PyQt5的第十三课-PyQt5复选框-QCheckBox控件事件应用" class="headerlink" title="PyQt5的第十三课 - PyQt5复选框 QCheckBox控件事件应用"></a>PyQt5的第十三课 - PyQt5复选框 QCheckBox控件事件应用</h1><h3 id="知识回顾-2"><a href="#知识回顾-2" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>文本框事件的改变,qlineEdit单行文本框</li><li>标签自适应adjustsize方法</li></ul><h3 id="复选框"><a href="#复选框" class="headerlink" title="复选框"></a>复选框</h3><ul><li>使用控件QCheckBox</li><li>使用格式</li><li>变量对象 = QCheckBox(显示文本,父容器)</li><li>这里的父容器可以是一个QWidget类型</li></ul><p>我们案例中的QFrame实际上本质是一个QWidget</p><h3 id="复选框状态改变信号"><a href="#复选框状态改变信号" class="headerlink" title="复选框状态改变信号"></a>复选框状态改变信号</h3><ul><li>使用statechanged信号,注意这个信号可以传以参数,这个参数是一个int类型.</li><li>使用格式:</li><li><code>self.复选框.stateChanged[int].connect(self.myState)</code></li><li><code>复选框.状态改变信号[整型参数].connect(类中的自定义方法)</code></li><li>使用案例:</li><li><code>self.ck1.stateChanged[int].connect(self.myState)</code></li></ul><h3 id="如何区分通过信号传递过来的不同控件"><a href="#如何区分通过信号传递过来的不同控件" class="headerlink" title="如何区分通过信号传递过来的不同控件?"></a>如何区分通过信号传递过来的不同控件?</h3><ul><li>直接通过self对象的sender方法就可以进行区分了</li></ul><h3 id="Qt中有很多枚举类表示"><a href="#Qt中有很多枚举类表示" class="headerlink" title="Qt中有很多枚举类表示"></a>Qt中有很多枚举类表示</h3><ul><li>比如我们今天学习的选中复选框使用2对应表示为Qt.Checked</li><li>写成枚举类型的好处就是方便我们阅读代码.</li></ul><h3 id="总结强调-2"><a href="#总结强调-2" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>复选框的状态改变事件statechanged</li><li>qt枚举</li><li>掌握把控件放到容器中qframe</li></ul><h1 id="PyQt5的第十四课-PyQt5滑块控件Qslider的应用"><a href="#PyQt5的第十四课-PyQt5滑块控件Qslider的应用" class="headerlink" title="PyQt5的第十四课 - PyQt5滑块控件Qslider的应用"></a>PyQt5的第十四课 - PyQt5滑块控件Qslider的应用</h1><h3 id="知识回顾-3"><a href="#知识回顾-3" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>掌握了复选框QCheckBox</li><li>枚举类中的值为2</li><li>在Qframe中的应用</li></ul><h3 id="Qslider控件"><a href="#Qslider控件" class="headerlink" title="Qslider控件"></a>Qslider控件</h3><ul><li>这个是一个滑块控件.用于方便左右滑动</li><li>往往这类滑动更多的用于屏幕可以触碰的设备</li><li>实则就是调用Qslider库</li><li>进行实例化后进行调用</li><li>使用格式:<br>  变量名称 = Qslider(方向,父容器)</li><li>水平方向值为1,垂直方向值为2(说白了你不写常量,你直接就写1,2都行了)    </li><li>这个控件可以水平放置,也可以垂直放置Qt.Vertical</li><li>应用举例:</li><li>QSlider(Qt.Horizontal.self)</li></ul><h3 id="枚举类的存在类库"><a href="#枚举类的存在类库" class="headerlink" title="枚举类的存在类库"></a>枚举类的存在类库</h3><ul><li>QtCore核心库</li><li></li></ul><h3 id="滑块控件的最值设置-范围设置"><a href="#滑块控件的最值设置-范围设置" class="headerlink" title="滑块控件的最值设置(范围设置)"></a>滑块控件的最值设置(范围设置)</h3><ul><li>最小值设置</li><li>举例设置最小值为0:</li><li><code>sl.setMinimum(0)</code></li><li>最大值设置</li><li>举例设置最大值为255:</li><li><code>sl.setMaximum(255)</code></li></ul><h3 id="滑块的滑动值变化事件"><a href="#滑块的滑动值变化事件" class="headerlink" title="滑块的滑动值变化事件"></a>滑块的滑动值变化事件</h3><ul><li><code>滑块的格式:滑块对象名称.valueChanged[int].connect(对应)</code></li><li><code>sl.valueChanged[int].connect(self.myValue)</code></li></ul><h3 id="总结强调-3"><a href="#总结强调-3" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握滑块控件Qslider的使用</li><li>掌握滑块值的事件</li><li>掌握枚举类库的使用</li></ul><h1 id="PyQt5的第十五课-PyQt5进度条QProgressBar应用"><a href="#PyQt5的第十五课-PyQt5进度条QProgressBar应用" class="headerlink" title="PyQt5的第十五课 - PyQt5进度条QProgressBar应用"></a>PyQt5的第十五课 - PyQt5进度条QProgressBar应用</h1><h3 id="知识回顾-4"><a href="#知识回顾-4" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>滑动控件qslider</li><li>关键:设置最大值,最小值,绝对范围</li><li>核心类库QtCore,枚举类Qt</li></ul><h3 id="进度条qprogressbar"><a href="#进度条qprogressbar" class="headerlink" title="进度条qprogressbar"></a>进度条qprogressbar</h3><p>使用思想:</p><ul><li>载入类库</li><li>初始化对象</li><li>设置最小值和最大值</li><li>时钟的使用QBasicTimer,跟槽方法对应类库中的timeevent</li></ul><h3 id="制作案例"><a href="#制作案例" class="headerlink" title="制作案例"></a>制作案例</h3><ul><li>界面由进度条和按钮组成</li><li>进度条的值范围为0-100</li><li>按钮的状态为:”开始”, “暂停”,”终止”</li><li>按钮需要控制进度条进度</li></ul><h3 id="导入时钟类库"><a href="#导入时钟类库" class="headerlink" title="导入时钟类库"></a>导入时钟类库</h3><p><code>from pyqt5.qtcore import qbasictimer</code></p><h3 id="初始化进度条"><a href="#初始化进度条" class="headerlink" title="初始化进度条"></a>初始化进度条</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 载入进度条</span></span><br><span class="line">self.pgb = QProgressBar(self) <span class="comment"># 类对象的初始化</span></span><br><span class="line">self.pgb.move(<span class="number">50</span>,<span class="number">50</span>) <span class="comment"># 将进度条移动到指定的位置</span></span><br><span class="line">self.pgb.resize(<span class="number">300</span>,<span class="number">20</span>) <span class="comment"># 设置进度条宽高</span></span><br></pre></td></tr></table></figure><h3 id="设置进度条的范围"><a href="#设置进度条的范围" class="headerlink" title="设置进度条的范围"></a>设置进度条的范围</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">self.pgb.setMinimum(<span class="number">0</span>)  <span class="comment"># 设置最小值</span></span><br><span class="line">self.pgb.setMaximum(<span class="number">100</span>) <span class="comment"># 设置最大值</span></span><br><span class="line">self.pgb.setValue(<span class="number">50</span>)   <span class="comment"># 设置当前进度</span></span><br></pre></td></tr></table></figure><h3 id="时钟控件"><a href="#时钟控件" class="headerlink" title="时钟控件"></a>时钟控件</h3><ul><li>做用:每搁多少时间执行一次时钟内部的代码</li><li>时间单位:毫秒</li><li>1秒 = 1000毫秒</li></ul><h3 id="QBasicTimer控价解析"><a href="#QBasicTimer控价解析" class="headerlink" title="QBasicTimer控价解析"></a>QBasicTimer控价解析</h3><ul><li>isActive方法:返回时钟控件是否开启,如果开启返回true,否则为false</li><li>start方法:使得时钟控件开启来,需要传入时钟间隔,时间单位为毫秒</li><li>简单的参数使用格式</li><li>start(时间,self)</li><li>stop方法:使得时钟控件关闭.</li><li>timerID方法:返回当前时钟控件的ID,主要用于多个时钟控件使用的时候,区分不同的时钟控件.</li><li>对应的槽方法是Qwidget控件自带的timerEvent事件.</li><li>时钟控件的每个多少时间要运行一次的代码就是在timerEvent方法中,我们在使用时钟控件的时候要重写这个方法</li></ul><h3 id="timerEvent方法"><a href="#timerEvent方法" class="headerlink" title="timerEvent方法"></a>timerEvent方法</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 声明一个时钟控件</span></span><br><span class="line">self.timer1 = QBasicTimer()</span><br><span class="line"><span class="comment"># 开始计时</span></span><br><span class="line">self.timer1.start(<span class="number">1000</span>,self)</span><br><span class="line"><span class="comment"># 这玩意是系统带的,自动就调用它,默认1秒钟一次</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">timerEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line">    self.pv += <span class="number">1</span></span><br><span class="line">    self.pgb.setValue(self.pv)   <span class="comment"># 设置当前进度</span></span><br></pre></td></tr></table></figure><h3 id="时钟控件状态切断的核心代码"><a href="#时钟控件状态切断的核心代码" class="headerlink" title="时钟控件状态切断的核心代码"></a>时钟控件状态切断的核心代码</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> self.timer1.isActive():  <span class="comment"># 检测是否开启</span></span><br><span class="line">        self.timer1.stop(<span class="number">50</span>, self)</span><br><span class="line">        self.btn.setText(<span class="string">&quot;开始&quot;</span>)  <span class="comment"># 这里的按钮的状态显示的是按钮下次的行为</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        self.timer1.start(<span class="number">50</span>, self)</span><br><span class="line">        self.btn.setText(<span class="string">&quot;停止&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="总结强调-4"><a href="#总结强调-4" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握Qprogressbar的控件的配置</li><li>掌握时钟控件的基本使用QBasicTimer</li><li>理解按钮控制时钟控件达到进度条的运行的思想.</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> PyQt5 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PyQt5学习笔记16-20</title>
      <link href="python/GUI/pyqt5/note/pyqt5-note16-19/"/>
      <url>python/GUI/pyqt5/note/pyqt5-note16-19/</url>
      
        <content type="html"><![CDATA[<h1 id="PyQt5的第十六课-PyQt5载入图片QPixmap应用"><a href="#PyQt5的第十六课-PyQt5载入图片QPixmap应用" class="headerlink" title="PyQt5的第十六课 - PyQt5载入图片QPixmap应用"></a>PyQt5的第十六课 - PyQt5载入图片QPixmap应用</h1><h3 id="知识回顾"><a href="#知识回顾" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>进度条qprogressbar</li><li>学会使用时钟控件QBasicTimer</li><li>学会重写事件timerEvent</li></ul><h3 id="案例-图片的载入与移除"><a href="#案例-图片的载入与移除" class="headerlink" title="案例:图片的载入与移除"></a>案例:图片的载入与移除</h3><ul><li>加入需要能够载入图片</li><li>增加移除图片按钮和添加图片按钮</li><li>当点击相应按钮后会有相应的功能</li></ul><h3 id="最终图片的显示载体QLabel"><a href="#最终图片的显示载体QLabel" class="headerlink" title="最终图片的显示载体QLabel"></a>最终图片的显示载体QLabel</h3><ul><li><p>功能:</p></li><li><p>显示文字</p></li><li><p>显示图片,载入QPixmap</p></li><li><p>默认情况下,label显示区域,是根据图片的大小进行显示的</p></li><li><p>如果设置label大小的话,只会显示图片的部分裁剪区域</p></li><li><p>使用方法:<code>lbl.setPixmap(图片实例化对象)</code></p></li><li><p><code>lbl.setPixmap(QPixmap(&quot;./img/th.jpg&quot;))</code></p></li><li><p>如和让图片自适应qlabel标签的区域呢?</p><h3 id="QPixmap类"><a href="#QPixmap类" class="headerlink" title="QPixmap类"></a>QPixmap类</h3></li><li><p>所在类库QtGUI</p></li><li><p>导入<br>from PyQt5.QtGui import Qpixmap</p></li><li><p>实例化图片对象:</p></li><li><p>QPixmap(图片路径) 返回一个实例化图片对象</p></li></ul><h3 id="总结强调"><a href="#总结强调" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握QPixmap载入图片对象与移除</li><li>掌握通过QLabel来显示图片与自适应大小</li></ul><h1 id="PyQt5的第十七课-PyQt5下拉列表控件QComboBox"><a href="#PyQt5的第十七课-PyQt5下拉列表控件QComboBox" class="headerlink" title="PyQt5的第十七课 - PyQt5下拉列表控件QComboBox"></a>PyQt5的第十七课 - PyQt5下拉列表控件QComboBox</h1><p>说白了就像以前那个js的地址联动似的</p><h3 id="知识回顾-1"><a href="#知识回顾-1" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>掌握QPixmap图片对象</li><li>掌握Qlabel控件装载图和调整图片</li></ul><h3 id="下拉列表-combobox"><a href="#下拉列表-combobox" class="headerlink" title="下拉列表 combobox"></a>下拉列表 combobox</h3><ul><li>主要用于选择,比如省市联动选择</li><li>必须要载入Qcombobox类</li><li>实例化类为一个对象,对这个对象进行配置,实则就是对下拉列表的配置</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">combox_1 = QComboBox(myframe1)</span><br><span class="line">combox_1.move(<span class="number">20</span>,<span class="number">0</span>)</span><br><span class="line">```        </span><br><span class="line">- 我们通过addItem来往combobox中装入项目.</span><br><span class="line">```python</span><br><span class="line">combox_1.addItem(<span class="string">&quot;请选择省份&quot;</span>)</span><br><span class="line">combox_1.addItem(<span class="string">&quot;浙江&quot;</span>)</span><br><span class="line">combox_1.addItem(<span class="string">&quot;江苏&quot;</span>)</span><br><span class="line">combox_1.addItem(<span class="string">&quot;安徽&quot;</span>)</span><br><span class="line">combox_1.addItem(<span class="string">&quot;北京&quot;</span>)</span><br></pre></td></tr></table></figure><ul><li>我们通过addItem来王combobox中装入项目</li></ul><p>用到clear方法将所有项目进行清空</p><h3 id="Combobox点击事件"><a href="#Combobox点击事件" class="headerlink" title="Combobox点击事件"></a>Combobox点击事件</h3><ul><li>理解为激活actived信号.</li><li>信号有两种传递方式</li><li>第一种传递传递字符串,这个实则传递的是选择的文本<br><code>combox_1.activated[str].connect(self.myActived)</code></li><li>第二种:传递整型变量,这个传递的是选择的索引.索引默认从0开始</li><li>第一项的索引是0,第二项的索引是1,依次类推</li><li>combo1.activated[int].connect(自定义槽方法)</li></ul><h3 id="案例省市联动选择"><a href="#案例省市联动选择" class="headerlink" title="案例省市联动选择"></a>案例省市联动选择</h3><ul><li>需要两个下拉列表</li><li>点击第一个下拉列表后,会联动第二个列表中的内容</li></ul><h3 id="扩展内容"><a href="#扩展内容" class="headerlink" title="扩展内容"></a>扩展内容</h3><p>下拉列表框也可以进行输入,但是需要对方法进行配置<br>配置setEditable为True:<br>combo1.setEditable(True)</p><h3 id="总结强调-1"><a href="#总结强调-1" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握qcombobox的载入布局与项目加载</li><li>掌握下拉列表的编辑和对应事件</li><li>掌握联动的思想</li></ul><h1 id="PyQt5的第十八课-PyQt5日历控件QCalendarWidget"><a href="#PyQt5的第十八课-PyQt5日历控件QCalendarWidget" class="headerlink" title="PyQt5的第十八课 - PyQt5日历控件QCalendarWidget"></a>PyQt5的第十八课 - PyQt5日历控件QCalendarWidget</h1><h3 id="知识回顾-2"><a href="#知识回顾-2" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>掌握了QCombobox下拉框,载入,配置(可编辑,不可编辑)</li><li>掌握联动的思想(省与市的联动),主要</li><li>用到actived信号</li></ul><h3 id="案例描述-日历控件的使用"><a href="#案例描述-日历控件的使用" class="headerlink" title="案例描述:日历控件的使用"></a>案例描述:日历控件的使用</h3><ul><li>制造一个垂直布局(盒子模型)</li><li>载入一个日历控件Qcalendarwidget和一个qlabel控件</li><li>要求在点击日历控件的日期的时候,能够将获取到的日期显示到我们的label上</li></ul><h3 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h3><ul><li>从库文件PyQt5.QtWidgets中导入日历控件</li><li>对日历控件进行实例化</li><li><code>cal = QCalendarWidget()</code></li><li>这里实例化的时候没有载入父容器,我们需要在后期将其载入父容器</li></ul><h3 id="盒子模型"><a href="#盒子模型" class="headerlink" title="盒子模型"></a>盒子模型</h3><ul><li>盒子模型,垂直布局<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">vlo = QVBoxLayout(self)</span><br><span class="line">vlo.addWidget(cal)</span><br></pre></td></tr></table></figure></li></ul><h3 id="字体设置"><a href="#字体设置" class="headerlink" title="字体设置"></a>字体设置</h3><ul><li>导入字体类</li><li>对字体进行实例化,以及将实例化对象载入使用<br><code>lbl.setFont(QFont(&quot;华文行楷&quot;,20))</code></li></ul><h3 id="日期类型的载入"><a href="#日期类型的载入" class="headerlink" title="日期类型的载入"></a>日期类型的载入</h3><ul><li>从pyqt5的核心库中载入日期类Qdate</li><li><code>from PyQt5.QtCore import QDate</code></li><li>默认的有实例的日期显示格式<br><code>PyQt5.QtCore.QDate(2019, 11, 15)</code></li></ul><h3 id="对日期进行格式化的技巧"><a href="#对日期进行格式化的技巧" class="headerlink" title="对日期进行格式化的技巧"></a>对日期进行格式化的技巧</h3><ul><li><p>问题是在我们的槽方法中无法对日期进行代码提示,关键的技巧就是对参数重新格式化为QDate类型就可以了</p></li><li><p>格式化日期使用toString方法来实现.</p></li><li><p>实现的时候,我们有两种方法:</p></li><li><p>方法一:使用y表示年的一位,M表示月,d表示日<br><code>self.lbl.setText(mydate.toString(&quot;yyyy-MM-dd&quot;))</code></p></li><li><p>方法二:使用系统中的已经定义好的方式</p></li><li><p>这种方式,已经定义好的枚举类<br><code>self.lbl.setText(mydate.toString(1))</code>或者<code>self.lbl.setText(mydate.toString(Qt.ISODate))</code></p></li></ul><h3 id="总结强调-2"><a href="#总结强调-2" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握日历控件QCalendarWidget的载入与配置.</li><li>掌握日历控件的信号控制</li><li>掌握日期格式化的几种方法.</li></ul><h1 id="PyQt5的第十久课-PyQt5菜单menu应用-新建多窗口"><a href="#PyQt5的第十久课-PyQt5菜单menu应用-新建多窗口" class="headerlink" title="PyQt5的第十久课 - PyQt5菜单menu应用,新建多窗口"></a>PyQt5的第十久课 - PyQt5菜单menu应用,新建多窗口</h1><h3 id="知识回顾-3"><a href="#知识回顾-3" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>掌握日历控件QCalendarWidget</li><li></li></ul><h3 id="案例-菜单"><a href="#案例-菜单" class="headerlink" title="案例:菜单"></a>案例:菜单</h3><ul><li>新建第一窗体</li><li>一级菜单的配置</li><li>二级菜单的配置</li><li>利用菜单功能实现界面跳转实现温馨提示</li></ul><h3 id="开发思路"><a href="#开发思路" class="headerlink" title="开发思路"></a>开发思路</h3><ul><li>导入类QMainWindow</li><li>使用Qmenu菜单类,这个菜单我们可以从窗体本身的方法进行获取</li><li>利用好Qmeun的功能,来实现多级菜单addAtion这是一个直接产生点击事件的行为<br>也可以用addMenu功能来增加子菜单</li><li>每次都要弹出新窗体,这个新窗体,我们要制作成全局的窗体</li><li>使用QMessagebox 来实现一个简单的帮助</li></ul><h3 id="一个空的模板"><a href="#一个空的模板" class="headerlink" title="一个空的模板"></a>一个空的模板</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QFont</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QCalendarWidget, QLabel, QVBoxLayout, QApplication, QWidget</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> QDate, Qt</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyClass</span>(<span class="params">QWidget</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.setWindowTitle(<span class="string">&quot;liujinr&quot;</span>)</span><br><span class="line">        self.setGeometry(<span class="number">300</span>,<span class="number">100</span>,<span class="number">400</span>,<span class="number">300</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        self.show()</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="载入菜单的简单功能"><a href="#载入菜单的简单功能" class="headerlink" title="载入菜单的简单功能"></a>载入菜单的简单功能</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">my_menu = self.menuBar()</span><br><span class="line">my_menu.addAction(<span class="string">&quot;新建&quot;</span>)</span><br><span class="line">my_menu.addAction(<span class="string">&quot;运行&quot;</span>)</span><br><span class="line">my_menu.addAction(<span class="string">&quot;调试&quot;</span>)</span><br><span class="line">my_menu.addAction(<span class="string">&quot;帮助&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="子菜单的书写"><a href="#子菜单的书写" class="headerlink" title="子菜单的书写"></a>子菜单的书写</h3><ul><li>这里要注意,直接将子菜单写在父菜单的下方</li><li>这样的好处,更多的也可以帮助我们进行二次理解</li><li>子菜单的添加,通过addMenu功能</li></ul><h3 id="子菜单的核心代码"><a href="#子菜单的核心代码" class="headerlink" title="子菜单的核心代码"></a>子菜单的核心代码</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">my_menu = self.menuBar()</span><br><span class="line">        file_menu = my_menu.addMenu(<span class="string">&quot;文件&quot;</span>)</span><br><span class="line">        file_menu.addAction(<span class="string">&#x27;新建&#x27;</span>)</span><br><span class="line">        recent_file = file_menu.addMenu(<span class="string">&quot;最近的&quot;</span>)</span><br><span class="line">        recent_file.addAction(<span class="string">&quot;文件1&quot;</span>)</span><br><span class="line">        recent_file.addAction(<span class="string">&quot;文件2&quot;</span>)</span><br><span class="line"><span class="comment"># 这里注意,子菜单的写法,一级一级下来的</span></span><br></pre></td></tr></table></figure><h3 id="对于新窗体的建议"><a href="#对于新窗体的建议" class="headerlink" title="对于新窗体的建议"></a>对于新窗体的建议</h3><ul><li>建议一个窗体就写一个类.那么每一次新的窗体出现的时候,就实例化这个类就OK了</li><li>注意:想要让这个窗体被一直死循环监听,必须要把这个窗体作为程序的全局变量</li><li>否则就会出现闪退现象</li></ul><h3 id="新建一个窗体的写法"><a href="#新建一个窗体的写法" class="headerlink" title="新建一个窗体的写法"></a>新建一个窗体的写法</h3><ul><li>直接写一个自定义的类窗体</li><li>将这个类窗体先不要show</li><li>将这个类窗体在main中进行实例化,作为全局变量</li><li>在槽的行为中,将这个窗体show出来</li></ul><h3 id="新建多个窗体"><a href="#新建多个窗体" class="headerlink" title="新建多个窗体"></a>新建多个窗体</h3><ul><li>这里是思想要实例化多个窗体,且这些窗体都是全局变量</li><li>这里要考虑用列表作为全局变量</li><li>此时,我们需要在自定义的类中书写show的代码</li></ul><h3 id="总结强调-3"><a href="#总结强调-3" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握菜单栏的书写</li><li>掌握菜单按钮的单击行为跳转功能</li><li>掌握子菜单的建立,</li><li>掌握多窗体的书写</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> PyQt5 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PyQt5案例汇总(简洁版)</title>
      <link href="python/GUI/pyqt5/demo/pyqt5-demo1/"/>
      <url>python/GUI/pyqt5/demo/pyqt5-demo1/</url>
      
        <content type="html"><![CDATA[<h3 id="01菜单栏"><a href="#01菜单栏" class="headerlink" title="01菜单栏"></a>01菜单栏</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow, QAction, qApp, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QIcon</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        exitAct = QAction(QIcon(<span class="string">&#x27;exit.png&#x27;</span>), <span class="string">&#x27;&amp;Exit&#x27;</span>, self)</span><br><span class="line">        exitAct.setShortcut(<span class="string">&#x27;Ctrl+Q&#x27;</span>)</span><br><span class="line">        exitAct.setStatusTip(<span class="string">&#x27;Exit application&#x27;</span>)</span><br><span class="line">        exitAct.triggered.connect(qApp.quit)</span><br><span class="line"></span><br><span class="line">        self.statusBar()</span><br><span class="line"></span><br><span class="line">        menubar = self.menuBar()</span><br><span class="line">        fileMenu = menubar.addMenu(<span class="string">&#x27;&amp;File&#x27;</span>)</span><br><span class="line">        fileMenu.addAction(exitAct)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Simple menu&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="02菜单栏"><a href="#02菜单栏" class="headerlink" title="02菜单栏++"></a>02菜单栏++</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QAction</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> qApp</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QIcon</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Demo</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 重新执行父类的初始化方法(默认的一些操作)</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        <span class="comment"># 加入自定义方法</span></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 设置菜单的图标</span></span><br><span class="line">        exitAct = QAction(QIcon(<span class="string">&#x27;exit.png&#x27;</span>),<span class="string">&#x27;&amp;Exit&#x27;</span>, self)</span><br><span class="line">        exitAct.setShortcut(<span class="string">&#x27;Ctrl+Q&#x27;</span>)</span><br><span class="line">        exitAct.setStatusTip(<span class="string">&#x27;Exit application&#x27;</span>)</span><br><span class="line">        exitAct.triggered.connect(qApp.quit)</span><br><span class="line"></span><br><span class="line">        self.statusBar()</span><br><span class="line"></span><br><span class="line">        menubar = self.menuBar()</span><br><span class="line">        file_menu = menubar.addMenu(<span class="string">&#x27;&amp;File&#x27;</span>)</span><br><span class="line">        file_menu.addAction(exitAct)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>,<span class="number">300</span>,<span class="number">300</span>,<span class="number">300</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;简单的菜单&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Demo()</span><br><span class="line">app.exec()</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="03简单的窗口-细致分析"><a href="#03简单的窗口-细致分析" class="headerlink" title="03简单的窗口(细致分析)"></a>03简单的窗口(细致分析)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by xiaoming</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这个简单的小例子展示的是一个小窗口。但是我们可以在这个小窗口上面做很多事情，改变大小，最大化，最小化等，这需要很多代码才能实现。这在很多应用中很常见，没必要每次都要重写这部分代码，Qt已经提供了这些功能。PyQt5是一个高级的工具集合，相比使用低级的工具，能省略上百行代码。</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入一些需要的模块</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="comment"># 这里面引入了qtwidgets模块,其中包含了基本的用户界面控件</span></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建app对象</span></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line"><span class="comment"># 每个pyqt5应用都必须创建一个应用对象</span></span><br><span class="line"><span class="comment"># sys.argv是一组命令行参数的列表</span></span><br><span class="line"><span class="comment"># python可以在shell里运行,这个参数提供对脚本控制的功能</span></span><br><span class="line">w = QWidget()</span><br><span class="line"><span class="comment"># qwidget是用户控件中的基本控件,提供了基本的应用构造器</span></span><br><span class="line"><span class="comment"># 默认情况下,构造器没有父级,没有父级的构造器称为窗口(window)</span></span><br><span class="line">w.resize(<span class="number">250</span>,<span class="number">450</span>)</span><br><span class="line"><span class="comment"># resize这个方法能够改变控件的大小,这里的意思的窗口宽250px,高450px</span></span><br><span class="line">w.move(<span class="number">300</span>,<span class="number">200</span>)</span><br><span class="line"><span class="comment"># move()是修改控件位置的方法.他把控件放置到屏幕坐标的(300,200位置)</span></span><br><span class="line"><span class="comment"># 注:屏幕坐标的原点是屏幕的左上角</span></span><br><span class="line">w.setWindowTitle(<span class="string">&#x27;我的第一个窗口&#x27;</span>)</span><br><span class="line"><span class="comment"># 这里给这个窗口添加了一个标题,标题在标题栏展示</span></span><br><span class="line"><span class="comment"># 虽然看起来是废话,但是以后回学习到各种栏,还是要注意一下,多了就懵逼了</span></span><br><span class="line">w.show()</span><br><span class="line"><span class="comment"># show()能让控件在桌面上显示出来.控件在内存中创建,之后才能在显示器上显示出来</span></span><br><span class="line">sys.exit(app.exec())</span><br><span class="line"><span class="comment"># 最后,我们进入了应用的主循环中,事件处理器这个时候开始工作.</span></span><br><span class="line"><span class="comment"># 主循环从窗口上接收事件,并把事件传入到派发到应用控件里.</span></span><br><span class="line"><span class="comment"># 当调用exit()方法或者直接销毁主控件时,主循环就会结束</span></span><br><span class="line"><span class="comment"># sys.exit()方法能确保主循环安全退出.外部环境能通知主控件怎么结束</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># exec_()之所以有个下划线,是因为exec是一个python的关键字</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="04带窗口图标"><a href="#04带窗口图标" class="headerlink" title="04带窗口图标"></a>04带窗口图标</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 首先还是要导入对应的模块</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QIcon</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 之前的例子是过程式编程,python当然支持面向对象编程</span></span><br><span class="line"><span class="comment"># 创建一个类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()  <span class="comment"># 使用initUI方法创建了一个GUI</span></span><br><span class="line"></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    面向对象编程最重要的三个部分是类(class),数据和方法.</span></span><br><span class="line"><span class="string">    我们创建了一个类的调用,这个类继承自QWidget.</span></span><br><span class="line"><span class="string">    这个就意味着,我们调用了两个构造器,一个是这个类本身的,一个是这个类继承的</span></span><br><span class="line"><span class="string">    super()构造器方法返回父级的对象.__init()方法是构造器的一个方法.</span></span><br><span class="line"><span class="string">    俗称初始化魔术方法</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">200</span>, <span class="number">700</span>, <span class="number">400</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;标题起啥都行&#x27;</span>)</span><br><span class="line">        self.setWindowIcon(QIcon(<span class="string">&#x27;logo.png&#x27;</span>))</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        上面三个方法都是继承自QWidget类.</span></span><br><span class="line"><span class="string">        setGeometry() 有两个作用: 把窗口放到屏幕上并且设置窗口大小.</span></span><br><span class="line"><span class="string">                                参数分别代表屏幕坐标的x y 和窗口大小的长和宽</span></span><br><span class="line"><span class="string">        setWindowTitle就是设置标题内容,不用多说</span></span><br><span class="line"><span class="string">        也就是说这个方法是 resize()和move()的合体.</span></span><br><span class="line"><span class="string">        最后一个方法就是添加图标,先创建一个QIcon对象,然后接受一个路径主辅材作为参数,显示图标</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">yingyong = QApplication(sys.argv)</span><br><span class="line">ex1 = Test()</span><br><span class="line">sys.exit(yingyong.exec_())</span><br><span class="line"></span><br><span class="line"><span class="comment"># 应用和示例的对象创立,主循环开始</span></span><br></pre></td></tr></table></figure><h3 id="05提示框"><a href="#05提示框" class="headerlink" title="05提示框"></a>05提示框</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 导入模块</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QToolTip</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QPushButton</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QFont</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 来直接来一个类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Demo</span>(<span class="params">QWidget</span>):</span>    <span class="comment">#继承自QWidget</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 初始化魔术方法直接上</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 父类的方法还原</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        <span class="comment"># 执行自己的方法</span></span><br><span class="line">        self.initUI()</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 这个字体的话,系统中有的都行</span></span><br><span class="line">        QToolTip.setFont(QFont(<span class="string">&#x27;微软雅黑&#x27;</span>,<span class="number">15</span>))</span><br><span class="line">        <span class="comment"># 这个 例子中,我们创建 了一个提示框</span></span><br><span class="line">        self.setToolTip(<span class="string">&#x27;不信了还&lt;b&gt;这是一个啥玩意&lt;/b&gt;&#x27;</span>)</span><br><span class="line">        <span class="comment"># 这个高,实在是高</span></span><br><span class="line">        <span class="comment"># html中的标签也能应用样式</span></span><br><span class="line">        <span class="comment"># 强，实在是强</span></span><br><span class="line">        btn = QPushButton(<span class="string">&#x27;点我&#x27;</span>,self)</span><br><span class="line">        <span class="comment"># 这个静态方法设置了提示框的字体,我们使用了15px的微软雅黑的字体</span></span><br><span class="line">        btn.setToolTip(<span class="string">&#x27;君不见黄河之水&lt;br&gt;天上来&#x27;</span>)</span><br><span class="line">        <span class="comment"># 调用setTooltip()创建提示框可以使用富文本格式的内容</span></span><br><span class="line">        btn.resize(btn.sizeHint())</span><br><span class="line">        btn.move(<span class="number">50</span>,<span class="number">70</span>)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">200</span>,<span class="number">150</span>,<span class="number">800</span>,<span class="number">450</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;标题就是没有标题&#x27;</span>)</span><br><span class="line">        <span class="comment"># 显示</span></span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex1 = Demo()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="06关闭窗口"><a href="#06关闭窗口" class="headerlink" title="06关闭窗口"></a>06关闭窗口</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;&gt;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">TODO 要做的可多了</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 关闭一个窗口最直观的方式就是点击标题栏的那个×,这个例子里面</span></span><br><span class="line"><span class="comment"># print(我们展示的是如何用程序关闭一个窗口)</span></span><br><span class="line"><span class="comment"># print(这里我们将解除)到一点single和slots的知识</span></span><br><span class="line"><span class="comment"># 本例子使用的是QPushButton组件类</span></span><br><span class="line"><span class="comment"># QPushButton(string text,Qwidget parent = None)</span></span><br><span class="line"><span class="comment"># text参数是想要显示的按钮名称,parent参数是放在按钮上的组件</span></span><br><span class="line"><span class="comment"># 在我们的例子里面,这个参数是QWidget.应用中的组件都是一层一层(继承而来的)</span></span><br><span class="line"><span class="comment"># 在这个层里,大部分的组件都有自己的父级,没有父级的组件,是顶级的窗口</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 还是tmd要导入对应的包和模块</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QPushButton</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> QCoreApplication</span><br><span class="line"><span class="comment"># 程序需要QtCore对象</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 上来先来一个类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 初始化魔术方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        qbtn = QPushButton(<span class="string">&#x27;退出就退出&#x27;</span>,self)</span><br><span class="line">        <span class="comment"># 创建一个继承自 QPushButton 的按钮.</span></span><br><span class="line">        <span class="comment"># 第一个参数是按钮的文本,第二个参数是按钮的父级组件</span></span><br><span class="line">        <span class="comment"># 这个例子中,父级组件就是我们创建的继承自QWidget 的 Example 类</span></span><br><span class="line">        qbtn.clicked.connect(QCoreApplication.instance().quit)</span><br><span class="line">        <span class="comment"># 事件传递系统在PyQt5内建的single和slot机制里面.点击按钮之后,信号会被捕捉并给出既定的反应</span></span><br><span class="line">        <span class="comment"># QCoreApplication包含了事件的主循环,它能添加和删除所有的事件</span></span><br><span class="line">        <span class="comment"># instance()创建 了一个它的实例.</span></span><br><span class="line">        <span class="comment"># QCoreApplication是在QApplication里创建的</span></span><br><span class="line">        <span class="comment"># 点击事件和能终止进程并退出应用的quit函数绑定在了一起.</span></span><br><span class="line">        <span class="comment"># 在发送者和接受者之间建立了通讯,发送者就是按钮,接受者就是应用对象</span></span><br><span class="line">        qbtn.move(<span class="number">50</span>,<span class="number">50</span>)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>,<span class="number">200</span>,<span class="number">250</span>,<span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&quot;退出按钮练习&quot;</span>)</span><br><span class="line">        <span class="comment"># 显示</span></span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">yingyong = QApplication(sys.argv)</span><br><span class="line">ex1 = Example()</span><br><span class="line">sys.exit(yingyong.exec_())</span><br><span class="line"><span class="comment"># 这里创建了一个点击之后就退出窗口的按钮</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="07消息盒子"><a href="#07消息盒子" class="headerlink" title="07消息盒子"></a>07消息盒子</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 导入模块</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span>  QWidget</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span>  QMessageBox</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span>  QApplication</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建一个类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        <span class="comment"># 执行自己的函数</span></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.setGeometry(<span class="number">300</span>,<span class="number">200</span>,<span class="number">250</span>,<span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;消息盒子&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">closeEvent</span>(<span class="params">self, QCloseEvent</span>):</span></span><br><span class="line"></span><br><span class="line">        reply = QMessageBox.question(self, <span class="string">&#x27;消息啊哈!&#x27;</span>,<span class="string">&quot;你确定你要退出了&quot;</span>,QMessageBox.yes | QMessageBox.No, QMessageBox.No)</span><br><span class="line">        <span class="keyword">if</span> reply == QMessageBox.Yes:</span><br><span class="line">            QCloseEvent.accept()</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            QCloseEvent.ignore()</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">demo = Example()</span><br><span class="line">app.exec_()</span><br></pre></td></tr></table></figure><h3 id="UI文件生成demo01模块（主窗口）"><a href="#UI文件生成demo01模块（主窗口）" class="headerlink" title="UI文件生成demo01模块（主窗口）"></a>UI文件生成demo01模块（主窗口）</h3><p><code>test.py</code>代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> *</span><br><span class="line"><span class="comment"># 导入生成的 py模块</span></span><br><span class="line"><span class="keyword">from</span> demo01 <span class="keyword">import</span> *</span><br><span class="line"><span class="comment"># 创建app</span></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line"><span class="comment"># 实例化主窗口对象</span></span><br><span class="line">w = QMainWindow()</span><br><span class="line"><span class="comment"># 实例化并调用初始化方法</span></span><br><span class="line">Ui_MainWindow().setupUi(w)</span><br><span class="line"><span class="comment"># 显示窗口</span></span><br><span class="line">w.show()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"><span class="keyword">pass</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> summer </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> PyQt5 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PyQt5案例汇总(完整版)</title>
      <link href="python/GUI/pyqt5/demo/pyqt5-demo2/"/>
      <url>python/GUI/pyqt5/demo/pyqt5-demo2/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p><a href="https://pypi.org/project/PyQt5/">PyQt5</a>是一套绑定Qt5的应用程序框架。他在Python 2.x和3.x中都是可用的。该教程使用的是Python3.x。</p><p>Qt库是一套最有用的GUI库。</p><p>PyQt5是作为一套Python模块实现的。他已经超过620个类和6000个函数与方法。他是一个运行在所有主流操作系统上的多平台组件，包括Unix,Windows和Mac OS。</p><h3 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h3><p>下面小编就给大家提供一些简单的pyqt5的案例,如有需要拿走不谢!!!</p><p>本文转载from:<a href="https://maicss.gitbooks.io/pyqt5/content/">PyQt5-Chinese-tutorial</a></p><h1 id="菜单栏和工具栏"><a href="#菜单栏和工具栏" class="headerlink" title="菜单栏和工具栏"></a>菜单栏和工具栏</h1><h3 id="01窗口居中"><a href="#01窗口居中" class="headerlink" title="01窗口居中"></a>01窗口居中</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 导入需要的包和模块</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QDesktopWidget</span><br><span class="line"><span class="comment"># QDesktopWidget这个库提供了用户的桌面信息,包括屏幕的大小</span></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建一个类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Ex</span>(<span class="params">QWidget</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.resize(<span class="number">250</span>,<span class="number">150</span>)</span><br><span class="line">        self.center()</span><br><span class="line">        <span class="comment"># 这个方法调用我们下面写的,实现对话框居中的方法</span></span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;chuangkou要居中&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">center</span>(<span class="params">self</span>):</span></span><br><span class="line">        qr = self.frameGeometry()</span><br><span class="line">        <span class="comment"># 得到了主窗口大小</span></span><br><span class="line">        print(<span class="string">&#x27;qr:&#x27;</span>,qr)</span><br><span class="line">        cp = QDesktopWidget().availableGeometry().center()</span><br><span class="line">        <span class="comment"># 获取显示器的分辨率,然后得到中间点的位置</span></span><br><span class="line">        print(<span class="string">&#x27;cp:&#x27;</span>,cp)</span><br><span class="line">        qr.moveCenter(cp)</span><br><span class="line">        <span class="comment"># 然后把自己的窗口的中心点放到qr的中心点</span></span><br><span class="line">        self.move(qr.topLeft())</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">demo1 = Ex()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="02-状态栏"><a href="#02-状态栏" class="headerlink" title="02 状态栏"></a>02 状态栏</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 导入需要的包和模块</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="comment"># from PyQt5.QtWidgets import QWidget</span></span><br><span class="line"><span class="comment"># from PyQt5.QtWidgets import QDesktopWidget</span></span><br><span class="line"><span class="comment"># QDesktopWidget这个库提供了用户的桌面信息,包括屏幕的大小</span></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Ex</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 状态栏是由这个创建的</span></span><br><span class="line">        self.statusBar().showMessage(<span class="string">&#x27;准备&#x27;</span>)</span><br><span class="line">        <span class="comment"># 调用QtGui.QMainWindow 类的 statusBar()方法</span></span><br><span class="line">        <span class="comment">#3 创建状态栏.第一次调用创建一个状态栏,返回一个状态栏对象.</span></span><br><span class="line">        <span class="comment">#3 showMessage()方法在状态栏上显示一条信息</span></span><br><span class="line">        self.setGeometry(<span class="number">300</span>,<span class="number">300</span>,<span class="number">250</span>,<span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;标题还是要取的&#x27;</span>)</span><br><span class="line">        <span class="comment">#显示</span></span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">demo1 = Ex()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="03菜单栏"><a href="#03菜单栏" class="headerlink" title="03菜单栏"></a>03菜单栏</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QAction</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> qApp</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QIcon</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Ex</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>(Ex, self).__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        exitAct = QAction(QIcon(<span class="string">&quot;exit.png&quot;</span>),<span class="string">&#x27;&amp;Exit&#x27;</span>,self)</span><br><span class="line">        print(exitAct)</span><br><span class="line">        exitAct.setShortcut(<span class="string">&quot;ctrl+q&quot;</span>)</span><br><span class="line">        exitAct.setStatusTip(<span class="string">&#x27;tuichu应用&#x27;</span>)</span><br><span class="line">        exitAct.triggered.connect(qApp.quit)</span><br><span class="line"></span><br><span class="line">        self.statusBar()</span><br><span class="line"></span><br><span class="line">        menubar = self.menuBar()</span><br><span class="line">        fileMenu = menubar.addMenu(<span class="string">&#x27;&amp;File&#x27;</span>)</span><br><span class="line">        fileMenu.addAction(exitAct)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>,<span class="number">300</span>,<span class="number">399</span>,<span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;决赛你电脑的&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">demo1 = Ex()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="04子菜单"><a href="#04子菜单" class="headerlink" title="04子菜单"></a>04子菜单</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow, QAction, QMenu, QApplication</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        menubar = self.menuBar()</span><br><span class="line">        fileMenu = menubar.addMenu(<span class="string">&#x27;File&#x27;</span>)</span><br><span class="line">        impMenu = QMenu(<span class="string">&#x27;Import&#x27;</span>, self)</span><br><span class="line">        impAct = QAction(<span class="string">&#x27;Import mail&#x27;</span>, self)</span><br><span class="line">        impMenu.addAction(impAct)</span><br><span class="line"></span><br><span class="line">        newAct = QAction(<span class="string">&#x27;New&#x27;</span>, self)</span><br><span class="line"></span><br><span class="line">        fileMenu.addAction(newAct)</span><br><span class="line">        fileMenu.addMenu(impMenu)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Submenu&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="05-勾选菜单"><a href="#05-勾选菜单" class="headerlink" title="05 勾选菜单"></a>05 勾选菜单</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow, QAction, QApplication</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.statusbar = self.statusBar()</span><br><span class="line">        self.statusbar.showMessage(<span class="string">&#x27;Ready&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        menubar = self.menuBar()</span><br><span class="line">        viewMenu = menubar.addMenu(<span class="string">&#x27;View&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 本例创建了一个行为菜单。这个行为／动作能切换状态栏显示或者隐藏。</span></span><br><span class="line">        viewStatAct = QAction(<span class="string">&#x27;View statusbar&#x27;</span>, self, checkable=<span class="literal">True</span>)</span><br><span class="line">        viewStatAct.setStatusTip(<span class="string">&#x27;View statusbar&#x27;</span>)        <span class="comment"># 用checkable选项创建一个能选中的菜单。</span></span><br><span class="line">        viewStatAct.setChecked(<span class="literal">True</span>)        <span class="comment"># 默认设置为选中状态</span></span><br><span class="line">        viewStatAct.triggered.connect(self.toggleMenu)</span><br><span class="line"></span><br><span class="line">        viewMenu.addAction(viewStatAct)</span><br><span class="line">        <span class="comment"># 依据选中状态切换状态栏的显示与否。</span></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Check menu&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">toggleMenu</span>(<span class="params">self, state</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> state:</span><br><span class="line">            self.statusbar.show()</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.statusbar.hide()</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">demo1 = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="06-右键菜单"><a href="#06-右键菜单" class="headerlink" title="06 右键菜单"></a>06 右键菜单</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow, qApp, QMenu, QApplication</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Context menu&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">contextMenuEvent</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        cmenu = QMenu(self)</span><br><span class="line"></span><br><span class="line">        newAct = cmenu.addAction(<span class="string">&quot;New&quot;</span>)</span><br><span class="line">        print(newAct)</span><br><span class="line">        opnAct = cmenu.addAction(<span class="string">&quot;Open&quot;</span>)</span><br><span class="line">        print(opnAct)</span><br><span class="line">        quitAct = cmenu.addAction(<span class="string">&quot;Quit&quot;</span>)</span><br><span class="line">        action = cmenu.exec_(self.mapToGlobal(event.pos()))</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> action == quitAct:</span><br><span class="line">            qApp.quit()</span><br><span class="line">        <span class="keyword">elif</span> action == opnAct:</span><br><span class="line">            print(<span class="string">&#x27;打开就打开&#x27;</span>)</span><br><span class="line">        <span class="keyword">elif</span> action == newAct:</span><br><span class="line">            print(<span class="string">&#x27;新建就新建&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="07工具栏"><a href="#07工具栏" class="headerlink" title="07工具栏"></a>07工具栏</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 菜单栏包含了所有的命令，工具栏就是常用的命令的集合。</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow, QAction, qApp, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QIcon</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        exitAct = QAction(QIcon(<span class="string">&#x27;logo.png&#x27;</span>), <span class="string">&#x27;Exit&#x27;</span>, self)</span><br><span class="line">        exitAct.setShortcut(<span class="string">&#x27;Ctrl+Q&#x27;</span>)</span><br><span class="line">        exitAct.triggered.connect(qApp.quit)</span><br><span class="line">        <span class="comment"># 和上面的菜单栏差不多，这里使用了一个行为对象，</span></span><br><span class="line">        <span class="comment"># 这个对象绑定了一个标签，一个图标和一个快捷键。</span></span><br><span class="line">        <span class="comment"># 这些行为被触发的时候，会调用QtGui.QMainWindow的quit方法退出应用。</span></span><br><span class="line">        self.toolbar = self.addToolBar(<span class="string">&#x27;Exit&#x27;</span>)</span><br><span class="line">        self.toolbar.addAction(exitAct)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Toolbar&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"><span class="comment"># 上面的例子中，我们创建了一个工具栏这个工具栏只有一个退出应用的动作</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="08主窗口-啥都有的呢"><a href="#08主窗口-啥都有的呢" class="headerlink" title="08主窗口(啥都有的呢)"></a>08主窗口(啥都有的呢)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;&gt;</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QTextEdit</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QAction</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QIcon</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        textEdit = QTextEdit()</span><br><span class="line">        self.setCentralWidget(textEdit)</span><br><span class="line"></span><br><span class="line">        exitAct = QAction(QIcon(<span class="string">&#x27;logo.png&#x27;</span>), <span class="string">&#x27;退退退&#x27;</span>, self)</span><br><span class="line">        exitAct.setShortcut(<span class="string">&#x27;Ctrl+Q&#x27;</span>)</span><br><span class="line">        exitAct.setStatusTip(<span class="string">&#x27;退出应用&#x27;</span>)</span><br><span class="line">        exitAct.triggered.connect(self.close)</span><br><span class="line"></span><br><span class="line">        self.statusBar()</span><br><span class="line"></span><br><span class="line">        menubar = self.menuBar()</span><br><span class="line">        fileMenu = menubar.addMenu(<span class="string">&#x27;文件&#x27;</span>)</span><br><span class="line">        fileMenu.addAction(exitAct)</span><br><span class="line"></span><br><span class="line">        toolbar = self.addToolBar(<span class="string">&#x27;退出&#x27;</span>)</span><br><span class="line">        toolbar.addAction(exitAct)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">350</span>, <span class="number">250</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;代码编辑工具&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h1 id="布局管理"><a href="#布局管理" class="headerlink" title="布局管理"></a>布局管理</h1><h3 id="09绝对定位的应用"><a href="#09绝对定位的应用" class="headerlink" title="09绝对定位的应用"></a>09绝对定位的应用</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QLabel, QApplication</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        lbl1 = QLabel(<span class="string">&#x27;Zetcode&#x27;</span>, self)</span><br><span class="line">        lbl1.move(<span class="number">15</span>, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">        lbl2 = QLabel(<span class="string">&#x27;tutorials&#x27;</span>, self)</span><br><span class="line">        lbl2.move(<span class="number">35</span>, <span class="number">40</span>)</span><br><span class="line"></span><br><span class="line">        lbl3 = QLabel(<span class="string">&#x27;for programmers&#x27;</span>, self)</span><br><span class="line">        lbl3.move(<span class="number">55</span>, <span class="number">70</span>)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">250</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Absolute&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"></span><br><span class="line"><span class="comment"># 绝对定位其实说白了就是使用相对于原点的像素来进行计算</span></span><br></pre></td></tr></table></figure><h3 id="10-盒子布局"><a href="#10-盒子布局" class="headerlink" title="10 盒子布局"></a>10 盒子布局</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QPushButton,</span><br><span class="line">    QHBoxLayout, QVBoxLayout, QApplication)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        okButton = QPushButton(<span class="string">&quot;OK&quot;</span>)</span><br><span class="line">        cancelButton = QPushButton(<span class="string">&quot;Cancel&quot;</span>)</span><br><span class="line"></span><br><span class="line">        hbox = QHBoxLayout()</span><br><span class="line">        hbox.addStretch(<span class="number">1</span>)</span><br><span class="line">        hbox.addWidget(okButton)</span><br><span class="line">        hbox.addWidget(cancelButton)</span><br><span class="line"></span><br><span class="line">        vbox = QVBoxLayout()</span><br><span class="line">        vbox.addStretch(<span class="number">1</span>)</span><br><span class="line">        vbox.addLayout(hbox)</span><br><span class="line"></span><br><span class="line">        self.setLayout(vbox)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Buttons&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="11-栅格布局-表格"><a href="#11-栅格布局-表格" class="headerlink" title="11 栅格布局(表格)"></a>11 栅格布局(表格)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QGridLayout,</span><br><span class="line">    QPushButton, QApplication)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        grid = QGridLayout()</span><br><span class="line">        self.setLayout(grid)</span><br><span class="line"></span><br><span class="line">        names = [<span class="string">&#x27;Cls&#x27;</span>, <span class="string">&#x27;Bck&#x27;</span>, <span class="string">&#x27;&#x27;</span>, <span class="string">&#x27;Close&#x27;</span>,</span><br><span class="line">                 <span class="string">&#x27;7&#x27;</span>, <span class="string">&#x27;8&#x27;</span>, <span class="string">&#x27;9&#x27;</span>, <span class="string">&#x27;/&#x27;</span>,</span><br><span class="line">                <span class="string">&#x27;4&#x27;</span>, <span class="string">&#x27;5&#x27;</span>, <span class="string">&#x27;6&#x27;</span>, <span class="string">&#x27;*&#x27;</span>,</span><br><span class="line">                 <span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>, <span class="string">&#x27;-&#x27;</span>,</span><br><span class="line">                <span class="string">&#x27;0&#x27;</span>, <span class="string">&#x27;.&#x27;</span>, <span class="string">&#x27;=&#x27;</span>, <span class="string">&#x27;+&#x27;</span>]</span><br><span class="line"></span><br><span class="line">        positions = [(i,j) <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">5</span>) <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">4</span>)]</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> position, name <span class="keyword">in</span> <span class="built_in">zip</span>(positions, names):</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> name == <span class="string">&#x27;&#x27;</span>:</span><br><span class="line">                <span class="keyword">continue</span></span><br><span class="line">            button = QPushButton(name)</span><br><span class="line">            grid.addWidget(button, *position)</span><br><span class="line"></span><br><span class="line">        self.move(<span class="number">300</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Calculator&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="12-制作提交反馈信息的布局"><a href="#12-制作提交反馈信息的布局" class="headerlink" title="12 制作提交反馈信息的布局"></a>12 制作提交反馈信息的布局</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> \</span><br><span class="line">    (QWidget, QLabel, QLineEdit, QTextEdit, QGridLayout, QApplication)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        title = QLabel(<span class="string">&#x27;Title&#x27;</span>)</span><br><span class="line">        author = QLabel(<span class="string">&#x27;Author&#x27;</span>)</span><br><span class="line">        review = QLabel(<span class="string">&#x27;Review&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        titleEdit = QLineEdit()</span><br><span class="line">        authorEdit = QLineEdit()</span><br><span class="line">        reviewEdit = QTextEdit()</span><br><span class="line"></span><br><span class="line">        grid = QGridLayout()</span><br><span class="line">        grid.setSpacing(<span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">        grid.addWidget(title, <span class="number">1</span>, <span class="number">0</span>)</span><br><span class="line">        grid.addWidget(titleEdit, <span class="number">1</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">        grid.addWidget(author, <span class="number">2</span>, <span class="number">0</span>)</span><br><span class="line">        grid.addWidget(authorEdit, <span class="number">2</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">        grid.addWidget(review, <span class="number">3</span>, <span class="number">0</span>)</span><br><span class="line">        grid.addWidget(reviewEdit, <span class="number">3</span>, <span class="number">1</span>, <span class="number">5</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">        self.setLayout(grid)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">350</span>, <span class="number">300</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Review&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h1 id="事件和信号"><a href="#事件和信号" class="headerlink" title="事件和信号"></a>事件和信号</h1><h3 id="13-信号和槽机制"><a href="#13-信号和槽机制" class="headerlink" title="13 信号和槽机制"></a>13 信号和槽机制</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">事件</span></span><br><span class="line"><span class="string">signals and slots 被其他人翻译成信号和槽机制，(⊙o⊙)…我这里还是不翻译好了。</span></span><br><span class="line"><span class="string">所有的应用都是事件驱动的。事件大部分都是由用户的行为产生的，当然也有其他的事件产生方式，</span></span><br><span class="line"><span class="string">比如网络的连接，窗口管理器或者定时器等。调用应用的exec_()方法时，应用会进入主循环，主循环会监听和分发事件。</span></span><br><span class="line"><span class="string">在事件模型中，有三个角色：</span></span><br><span class="line"><span class="string">事件源</span></span><br><span class="line"><span class="string">事件</span></span><br><span class="line"><span class="string">事件目标</span></span><br><span class="line"><span class="string">事件源就是发生了状态改变的对象。事件是这个对象状态改变的内容。</span></span><br><span class="line"><span class="string">事件目标是事件想作用的目标。事件源绑定事件处理函数，然后作用于事件目标身上。</span></span><br><span class="line"><span class="string">PyQt5处理事件方面有个signal and slot机制。Signals and slots用于对象间的通讯。</span></span><br><span class="line"><span class="string">事件触发的时候，发生一个signal，slot是用来被Python调用的</span></span><br><span class="line"><span class="string">（相当于一个句柄？这个词也好恶心，就是相当于事件的绑定函数）slot只有在事件触发的时候才能调用。</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> \</span><br><span class="line">    (QWidget, QLCDNumber, QSlider, QVBoxLayout, QApplication)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        lcd = QLCDNumber(self)</span><br><span class="line">        print(<span class="string">&quot;lcd:&quot;</span>,lcd)</span><br><span class="line">        sld = QSlider(Qt.Horizontal, self)</span><br><span class="line">        print(<span class="string">&quot;sld&quot;</span>,sld)</span><br><span class="line">        vbox = QVBoxLayout()</span><br><span class="line">        print(vbox)</span><br><span class="line">        vbox.addWidget(lcd)</span><br><span class="line">        vbox.addWidget(sld)</span><br><span class="line"></span><br><span class="line">        self.setLayout(vbox)</span><br><span class="line">        print(lcd.display)</span><br><span class="line">        sld.valueChanged.connect(lcd.display)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">250</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;信号和槽机制的&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="14-重构事件处理器"><a href="#14-重构事件处理器" class="headerlink" title="14 重构事件处理器"></a>14 重构事件处理器</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">250</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;事件的手&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">keyPressEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> e.key() == Qt.Key_Escape:</span><br><span class="line">            self.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="15-事件对像"><a href="#15-事件对像" class="headerlink" title="15 事件对像"></a>15 事件对像</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication, QGridLayout, QLabel</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        grid = QGridLayout()</span><br><span class="line">        grid.setSpacing(<span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">        x = <span class="number">0</span></span><br><span class="line">        y = <span class="number">0</span></span><br><span class="line"></span><br><span class="line">        self.text = <span class="string">&quot;x: &#123;0&#125;,  y: &#123;1&#125;&quot;</span>.<span class="built_in">format</span>(x, y)</span><br><span class="line"></span><br><span class="line">        self.label = QLabel(self.text, self)</span><br><span class="line">        grid.addWidget(self.label, <span class="number">0</span>, <span class="number">0</span>, Qt.AlignTop)</span><br><span class="line"></span><br><span class="line">        self.setMouseTracking(<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">        self.setLayout(grid)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">350</span>, <span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Event object&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">mouseMoveEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        x = e.x()</span><br><span class="line">        y = e.y()</span><br><span class="line"></span><br><span class="line">        text = <span class="string">&quot;x: &#123;0&#125;,  y: &#123;1&#125;&quot;</span>.<span class="built_in">format</span>(x, y)</span><br><span class="line">        self.label.setText(text)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="16事件发送"><a href="#16事件发送" class="headerlink" title="16事件发送"></a>16事件发送</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow, QPushButton, QApplication</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        btn1 = QPushButton(<span class="string">&quot;按钮老大&quot;</span>, self)</span><br><span class="line">        btn1.move(<span class="number">30</span>, <span class="number">50</span>)</span><br><span class="line"></span><br><span class="line">        btn2 = QPushButton(<span class="string">&quot;按钮老二&quot;</span>, self)</span><br><span class="line">        btn2.move(<span class="number">150</span>, <span class="number">50</span>)</span><br><span class="line"></span><br><span class="line">        btn1.clicked.connect(self.buttonClicked)</span><br><span class="line">        btn2.clicked.connect(self.buttonClicked)</span><br><span class="line"></span><br><span class="line">        self.statusBar()</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">290</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;事件发送&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">buttonClicked</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        sender = self.sender()</span><br><span class="line">        self.statusBar().showMessage(sender.text() + <span class="string">&#x27;被按那儿了&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="17-信号发送"><a href="#17-信号发送" class="headerlink" title="17 信号发送"></a>17 信号发送</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> pyqtSignal, QObject</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow, QApplication</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Communicate</span>(<span class="params">QObject</span>):</span></span><br><span class="line"></span><br><span class="line">    closeApp = pyqtSignal()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.c = Communicate()</span><br><span class="line">        self.c.closeApp.connect(self.close)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">290</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Emit signal&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">mousePressEvent</span>(<span class="params">self, event</span>):</span></span><br><span class="line"></span><br><span class="line">        self.c.closeApp.emit()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h1 id="对话框"><a href="#对话框" class="headerlink" title="对话框"></a>对话框</h1><h3 id="18-对话框-能够输入文字呦呦"><a href="#18-对话框-能够输入文字呦呦" class="headerlink" title="18 对话框(能够输入文字呦呦)"></a>18 对话框(能够输入文字呦呦)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QPushButton, QLineEdit,</span><br><span class="line">    QInputDialog, QApplication)</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.btn = QPushButton(<span class="string">&#x27;Dialog&#x27;</span>, self)</span><br><span class="line">        self.btn.move(<span class="number">20</span>, <span class="number">20</span>)</span><br><span class="line">        self.btn.clicked.connect(self.showDialog)</span><br><span class="line"></span><br><span class="line">        self.le = QLineEdit(self)</span><br><span class="line">        self.le.move(<span class="number">130</span>, <span class="number">22</span>)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">290</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Input dialog&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">showDialog</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        text, ok = QInputDialog.getText(self, <span class="string">&#x27;Input Dialog&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;Enter your name:&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> ok:</span><br><span class="line">            self.le.setText(<span class="built_in">str</span>(text))</span><br><span class="line"></span><br><span class="line">        print(text+<span class="string">&quot;哈哈&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="19-选取颜色-NB坏了"><a href="#19-选取颜色-NB坏了" class="headerlink" title="19 选取颜色(NB坏了)"></a>19 选取颜色(NB坏了)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;QColorDialog提供颜色的选择&gt;</span></span><br><span class="line"><span class="comment"># TODO 这个厉害,直接调用系统的颜色选择框</span></span><br><span class="line"><span class="comment"># TODO 强,实在是强</span></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QPushButton, QFrame,</span><br><span class="line">    QColorDialog, QApplication)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QColor</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        col = QColor(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        self.btn = QPushButton(<span class="string">&#x27;Dialog&#x27;</span>, self)</span><br><span class="line">        self.btn.move(<span class="number">20</span>, <span class="number">20</span>)</span><br><span class="line"></span><br><span class="line">        self.btn.clicked.connect(self.showDialog)</span><br><span class="line"></span><br><span class="line">        self.frm = QFrame(self)</span><br><span class="line">        self.frm.setStyleSheet(<span class="string">&quot;QWidget &#123; background-color: %s &#125;&quot;</span></span><br><span class="line">            % col.name())</span><br><span class="line">        self.frm.setGeometry(<span class="number">130</span>, <span class="number">22</span>, <span class="number">100</span>, <span class="number">100</span>)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">250</span>, <span class="number">180</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Color dialog&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">showDialog</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        col = QColorDialog.getColor()</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> col.isValid():</span><br><span class="line">            self.frm.setStyleSheet(<span class="string">&quot;QWidget &#123; background-color: %s &#125;&quot;</span></span><br><span class="line">                % col.name())</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>加油,都看到一半了你!!!</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                 神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="20-选择字体"><a href="#20-选择字体" class="headerlink" title="20 选择字体"></a>20 选择字体</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QVBoxLayout, QPushButton,</span><br><span class="line">    QSizePolicy, QLabel, QFontDialog, QApplication)</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        vbox = QVBoxLayout()</span><br><span class="line"></span><br><span class="line">        btn = QPushButton(<span class="string">&#x27;来来来&#x27;</span>, self)</span><br><span class="line">        btn.setSizePolicy(QSizePolicy.Fixed,</span><br><span class="line">            QSizePolicy.Fixed)</span><br><span class="line"></span><br><span class="line">        btn.move(<span class="number">20</span>, <span class="number">20</span>)</span><br><span class="line"></span><br><span class="line">        vbox.addWidget(btn)</span><br><span class="line"></span><br><span class="line">        btn.clicked.connect(self.showDialog)</span><br><span class="line"></span><br><span class="line">        self.lbl = QLabel(<span class="string">&#x27;Knowledge only matters&#x27;</span>, self)</span><br><span class="line">        self.lbl.move(<span class="number">130</span>, <span class="number">20</span>)</span><br><span class="line"></span><br><span class="line">        vbox.addWidget(self.lbl)</span><br><span class="line">        self.setLayout(vbox)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">250</span>, <span class="number">180</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;字体目录&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">showDialog</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        font, ok = QFontDialog.getFont()</span><br><span class="line">        <span class="keyword">if</span> ok:</span><br><span class="line">            self.lbl.setFont(font)</span><br><span class="line">        print(<span class="string">&#x27;选择的字体是&#x27;</span>,end=<span class="string">&quot;&quot;</span>)</span><br><span class="line">        print(font)</span><br><span class="line">        print(<span class="built_in">type</span>(font))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="21-选择文件"><a href="#21-选择文件" class="headerlink" title="21 选择文件"></a>21 选择文件</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> \</span><br><span class="line">    (QMainWindow, QTextEdit, QAction, QFileDialog, QApplication)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QIcon</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QMainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.textEdit = QTextEdit()</span><br><span class="line">        self.setCentralWidget(self.textEdit)</span><br><span class="line">        self.statusBar()</span><br><span class="line"></span><br><span class="line">        openFile = QAction(QIcon(<span class="string">&#x27;images/open.png&#x27;</span>), <span class="string">&#x27;Open&#x27;</span>, self)</span><br><span class="line">        openFile.setShortcut(<span class="string">&#x27;Ctrl+O&#x27;</span>)</span><br><span class="line">        openFile.setStatusTip(<span class="string">&#x27;打开一个新的文件&#x27;</span>)</span><br><span class="line">        openFile.triggered.connect(self.showDialog)</span><br><span class="line"></span><br><span class="line">        menubar = self.menuBar()</span><br><span class="line">        fileMenu = menubar.addMenu(<span class="string">&#x27;&amp;文件&#x27;</span>)</span><br><span class="line">        fileMenu.addAction(openFile)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">350</span>, <span class="number">300</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;File dialog&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">showDialog</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        fname = QFileDialog.getOpenFileName(self, <span class="string">&#x27;Open file&#x27;</span>, <span class="string">&#x27;/home&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> fname[<span class="number">0</span>]:</span><br><span class="line">            f = <span class="built_in">open</span>(fname[<span class="number">0</span>], <span class="string">&#x27;r&#x27;</span>)</span><br><span class="line"></span><br><span class="line">            <span class="keyword">with</span> f:</span><br><span class="line">                data = f.read()</span><br><span class="line">                self.textEdit.setText(data)</span><br><span class="line">                print(data)</span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h1 id="控件"><a href="#控件" class="headerlink" title="控件"></a>控件</h1><h3 id="22-QCheckBox是啥玩意"><a href="#22-QCheckBox是啥玩意" class="headerlink" title="22 QCheckBox是啥玩意"></a>22 QCheckBox是啥玩意</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QCheckBox, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        cb = QCheckBox(<span class="string">&#x27;改改改&#x27;</span>, self)</span><br><span class="line">        cb.move(<span class="number">20</span>, <span class="number">20</span>)</span><br><span class="line">        cb.toggle()</span><br><span class="line">        cb.stateChanged.connect(self.changeTitle)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">250</span>, <span class="number">150</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;真正的标题&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">changeTitle</span>(<span class="params">self, state</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> state == Qt.Checked:</span><br><span class="line">            self.setWindowTitle(<span class="string">&#x27;假装有标题&#x27;</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.setWindowTitle(<span class="string">&#x27;没了&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="23-切换按钮"><a href="#23-切换按钮" class="headerlink" title="23 切换按钮"></a>23 切换按钮</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QPushButton,</span><br><span class="line">    QFrame, QApplication)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QColor</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.col = QColor(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        redb = QPushButton(<span class="string">&#x27;Red&#x27;</span>, self)</span><br><span class="line">        redb.setCheckable(<span class="literal">True</span>)</span><br><span class="line">        redb.move(<span class="number">10</span>, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">        redb.clicked[<span class="built_in">bool</span>].connect(self.setColor)</span><br><span class="line"></span><br><span class="line">        greenb = QPushButton(<span class="string">&#x27;Green&#x27;</span>, self)</span><br><span class="line">        greenb.setCheckable(<span class="literal">True</span>)</span><br><span class="line">        greenb.move(<span class="number">10</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        greenb.clicked[<span class="built_in">bool</span>].connect(self.setColor)</span><br><span class="line"></span><br><span class="line">        blueb = QPushButton(<span class="string">&#x27;Blue&#x27;</span>, self)</span><br><span class="line">        blueb.setCheckable(<span class="literal">True</span>)</span><br><span class="line">        blueb.move(<span class="number">10</span>, <span class="number">110</span>)</span><br><span class="line"></span><br><span class="line">        blueb.clicked[<span class="built_in">bool</span>].connect(self.setColor)</span><br><span class="line"></span><br><span class="line">        self.square = QFrame(self)</span><br><span class="line">        self.square.setGeometry(<span class="number">150</span>, <span class="number">20</span>, <span class="number">100</span>, <span class="number">100</span>)</span><br><span class="line">        self.square.setStyleSheet(<span class="string">&quot;QWidget &#123; background-color: %s &#125;&quot;</span> %</span><br><span class="line">            self.col.name())</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">280</span>, <span class="number">170</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Toggle button&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">setColor</span>(<span class="params">self, pressed</span>):</span></span><br><span class="line"></span><br><span class="line">        source = self.sender()</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> pressed:</span><br><span class="line">            val = <span class="number">255</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            val = <span class="number">0</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> source.text() == <span class="string">&quot;Red&quot;</span>:</span><br><span class="line">            self.col.setRed(val)</span><br><span class="line">        <span class="keyword">elif</span> source.text() == <span class="string">&quot;Green&quot;</span>:</span><br><span class="line">            self.col.setGreen(val)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.col.setBlue(val)</span><br><span class="line"></span><br><span class="line">        self.square.setStyleSheet(<span class="string">&quot;QFrame &#123; background-color: %s &#125;&quot;</span> %</span><br><span class="line">            self.col.name())</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="24-滑块是个好东西"><a href="#24-滑块是个好东西" class="headerlink" title="24 滑块是个好东西"></a>24 滑块是个好东西</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QSlider,</span><br><span class="line">                             QLabel, QApplication)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPixmap</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        sld = QSlider(Qt.Horizontal, self)</span><br><span class="line">        sld.setFocusPolicy(Qt.NoFocus)</span><br><span class="line">        sld.setGeometry(<span class="number">30</span>, <span class="number">40</span>, <span class="number">100</span>, <span class="number">30</span>)</span><br><span class="line">        sld.valueChanged[<span class="built_in">int</span>].connect(self.changeValue)</span><br><span class="line"></span><br><span class="line">        self.label = QLabel(self)</span><br><span class="line">        self.label.setPixmap(QPixmap(<span class="string">&#x27;images/logo.png&#x27;</span>))</span><br><span class="line">        self.label.setGeometry(<span class="number">160</span>, <span class="number">40</span>, <span class="number">80</span>, <span class="number">30</span>)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">280</span>, <span class="number">170</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;s什么鸡儿玩意r&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">changeValue</span>(<span class="params">self, value</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> value == <span class="number">0</span>:</span><br><span class="line">            self.label.setPixmap(QPixmap(<span class="string">&#x27;images/1.png&#x27;</span>))</span><br><span class="line">        <span class="keyword">elif</span> value &gt; <span class="number">0</span> <span class="keyword">and</span> value &lt;= <span class="number">30</span>:</span><br><span class="line">            self.label.setPixmap(QPixmap(<span class="string">&#x27;images/2.png&#x27;</span>))</span><br><span class="line">        <span class="keyword">elif</span> value &gt; <span class="number">30</span> <span class="keyword">and</span> value &lt; <span class="number">80</span>:</span><br><span class="line">            self.label.setPixmap(QPixmap(<span class="string">&#x27;images/3.png&#x27;</span>))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.label.setPixmap(QPixmap(<span class="string">&#x27;images/4.png&#x27;</span>))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="25-进度条"><a href="#25-进度条" class="headerlink" title="25 进度条"></a>25 进度条</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QProgressBar,</span><br><span class="line">    QPushButton, QApplication)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> QBasicTimer</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.pbar = QProgressBar(self)</span><br><span class="line">        self.pbar.setGeometry(<span class="number">30</span>, <span class="number">40</span>, <span class="number">200</span>, <span class="number">25</span>)</span><br><span class="line"></span><br><span class="line">        self.btn = QPushButton(<span class="string">&#x27;走你&#x27;</span>, self)</span><br><span class="line">        self.btn.move(<span class="number">40</span>, <span class="number">80</span>)</span><br><span class="line">        self.btn.clicked.connect(self.doAction)</span><br><span class="line"></span><br><span class="line">        self.timer = QBasicTimer()</span><br><span class="line">        self.step = <span class="number">0</span></span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">280</span>, <span class="number">170</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;进度条就比较强了&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">timerEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> self.step &gt;= <span class="number">200</span>:</span><br><span class="line">            self.timer.stop()</span><br><span class="line">            self.btn.setText(<span class="string">&#x27;完成吧&#x27;</span>)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line"></span><br><span class="line">        self.step = self.step + <span class="number">1</span></span><br><span class="line">        self.pbar.setValue(self.step)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">doAction</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> self.timer.isActive():</span><br><span class="line">            self.timer.stop()</span><br><span class="line">            self.btn.setText(<span class="string">&#x27;走走走&#x27;</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.timer.start(<span class="number">200</span>, self)</span><br><span class="line">            self.btn.setText(<span class="string">&#x27;停,呗走了&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="26-日历"><a href="#26-日历" class="headerlink" title="26 日历"></a>26 日历</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QCalendarWidget,</span><br><span class="line">    QLabel, QApplication, QVBoxLayout)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> QDate</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        vbox = QVBoxLayout(self)</span><br><span class="line"></span><br><span class="line">        cal = QCalendarWidget(self)</span><br><span class="line">        cal.setGridVisible(<span class="literal">True</span>)</span><br><span class="line">        cal.clicked[QDate].connect(self.showDate)</span><br><span class="line"></span><br><span class="line">        vbox.addWidget(cal)</span><br><span class="line"></span><br><span class="line">        self.lbl = QLabel(self)</span><br><span class="line">        date = cal.selectedDate()</span><br><span class="line">        self.lbl.setText(date.toString())</span><br><span class="line"></span><br><span class="line">        vbox.addWidget(self.lbl)</span><br><span class="line"></span><br><span class="line">        self.setLayout(vbox)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">350</span>, <span class="number">300</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;看日历，认准我&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">showDate</span>(<span class="params">self, date</span>):</span></span><br><span class="line"></span><br><span class="line">        self.lbl.setText(date.toString())</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="27-图片"><a href="#27-图片" class="headerlink" title="27 图片"></a>27 图片</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QHBoxLayout,</span><br><span class="line">    QLabel, QApplication)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPixmap</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        hbox = QHBoxLayout(self)</span><br><span class="line">        pixmap = QPixmap(<span class="string">&quot;images/09f04&quot;</span>)</span><br><span class="line"></span><br><span class="line">        lbl = QLabel(self)</span><br><span class="line">        lbl.setPixmap(pixmap)</span><br><span class="line"></span><br><span class="line">        hbox.addWidget(lbl)</span><br><span class="line">        self.setLayout(hbox)</span><br><span class="line"></span><br><span class="line">        self.move(<span class="number">300</span>, <span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Red Rock&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="28行编辑"><a href="#28行编辑" class="headerlink" title="28行编辑"></a>28行编辑</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> \</span><br><span class="line">    (QWidget, QLabel, QLineEdit, QApplication)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.lbl = QLabel(self)</span><br><span class="line">        qle = QLineEdit(self)</span><br><span class="line"></span><br><span class="line">        qle.move(<span class="number">60</span>, <span class="number">100</span>)</span><br><span class="line">        self.lbl.move(<span class="number">60</span>, <span class="number">40</span>)</span><br><span class="line"></span><br><span class="line">        qle.textChanged[<span class="built_in">str</span>].connect(self.onChanged)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">280</span>, <span class="number">170</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;QLineEdit&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">onChanged</span>(<span class="params">self, text</span>):</span></span><br><span class="line">        self.lbl.setText(text)</span><br><span class="line">        self.lbl.adjustSize()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="29-QSplitter是啥玩意呢"><a href="#29-QSplitter是啥玩意呢" class="headerlink" title="29 QSplitter是啥玩意呢?"></a>29 QSplitter是啥玩意呢?</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QHBoxLayout, QFrame,</span><br><span class="line">    QSplitter, QStyleFactory, QApplication)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        hbox = QHBoxLayout(self)</span><br><span class="line"></span><br><span class="line">        topleft = QFrame(self)</span><br><span class="line">        topleft.setFrameShape(QFrame.StyledPanel)</span><br><span class="line"></span><br><span class="line">        topright = QFrame(self)</span><br><span class="line">        topright.setFrameShape(QFrame.StyledPanel)</span><br><span class="line"></span><br><span class="line">        bottom = QFrame(self)</span><br><span class="line">        bottom.setFrameShape(QFrame.StyledPanel)</span><br><span class="line"></span><br><span class="line">        splitter1 = QSplitter(Qt.Horizontal)</span><br><span class="line">        splitter1.addWidget(topleft)</span><br><span class="line">        splitter1.addWidget(topright)</span><br><span class="line"></span><br><span class="line">        splitter2 = QSplitter(Qt.Vertical)</span><br><span class="line">        splitter2.addWidget(splitter1)</span><br><span class="line">        splitter2.addWidget(bottom)</span><br><span class="line"></span><br><span class="line">        hbox.addWidget(splitter2)</span><br><span class="line">        self.setLayout(hbox)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">400</span>, <span class="number">300</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;QSplitter&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">onChanged</span>(<span class="params">self, text</span>):</span></span><br><span class="line"></span><br><span class="line">        self.lbl.setText(text)</span><br><span class="line">        self.lbl.adjustSize()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="30-下拉选框"><a href="#30-下拉选框" class="headerlink" title="30 下拉选框"></a>30 下拉选框</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QLabel,</span><br><span class="line">    QComboBox, QApplication)</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.lbl = QLabel(<span class="string">&quot;Ubuntu&quot;</span>, self)</span><br><span class="line"></span><br><span class="line">        combo = QComboBox(self)</span><br><span class="line">        combo.addItem(<span class="string">&quot;Ubuntu&quot;</span>)</span><br><span class="line">        combo.addItem(<span class="string">&quot;Windows&quot;</span>)</span><br><span class="line">        combo.addItem(<span class="string">&quot;centos&quot;</span>)</span><br><span class="line">        combo.addItem(<span class="string">&quot;deepin&quot;</span>)</span><br><span class="line">        combo.addItem(<span class="string">&quot;redhat&quot;</span>)</span><br><span class="line">        combo.addItem(<span class="string">&quot;debain&quot;</span>)</span><br><span class="line">        combo.move(<span class="number">50</span>, <span class="number">50</span>)</span><br><span class="line">        self.lbl.move(<span class="number">50</span>, <span class="number">150</span>)</span><br><span class="line"></span><br><span class="line">        combo.activated[<span class="built_in">str</span>].connect(self.onActivated)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">200</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;下拉选框练习 &#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">onActivated</span>(<span class="params">self, text</span>):</span></span><br><span class="line"></span><br><span class="line">        self.lbl.setText(text)</span><br><span class="line">        self.lbl.adjustSize()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">ex = Example()</span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h1 id="拖拽"><a href="#拖拽" class="headerlink" title="拖拽"></a>拖拽</h1><h3 id="31-简单的拖放"><a href="#31-简单的拖放" class="headerlink" title="31 简单的拖放"></a>31 简单的拖放</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QPushButton, QWidget,</span><br><span class="line">    QLineEdit, QApplication)</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Button</span>(<span class="params">QPushButton</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, title, parent</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__(title, parent)</span><br><span class="line"></span><br><span class="line">        self.setAcceptDrops(<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">dragEnterEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> e.mimeData().hasFormat(<span class="string">&#x27;text/plain&#x27;</span>):</span><br><span class="line">            e.accept()</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            e.ignore()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">dropEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        self.setText(e.mimeData().text())</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        edit = QLineEdit(<span class="string">&#x27;&#x27;</span>, self)</span><br><span class="line">        edit.setDragEnabled(<span class="literal">True</span>)</span><br><span class="line">        edit.move(<span class="number">30</span>, <span class="number">65</span>)</span><br><span class="line"></span><br><span class="line">        button = Button(<span class="string">&quot;Button&quot;</span>, self)</span><br><span class="line">        button.move(<span class="number">190</span>, <span class="number">65</span>)</span><br><span class="line"></span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Simple drag and drop&#x27;</span>)</span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">150</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    ex.show()</span><br><span class="line">    app.exec_()</span><br></pre></td></tr></table></figure><h3 id="32-拖放按钮组件"><a href="#32-拖放按钮组件" class="headerlink" title="32 拖放按钮组件"></a>32 拖放按钮组件</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QPushButton, QWidget, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt, QMimeData</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QDrag</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Button</span>(<span class="params">QPushButton</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, title, parent</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__(title, parent)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">mouseMoveEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> e.buttons() != Qt.RightButton:</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line"></span><br><span class="line">        mimeData = QMimeData()</span><br><span class="line"></span><br><span class="line">        drag = QDrag(self)</span><br><span class="line">        drag.setMimeData(mimeData)</span><br><span class="line">        drag.setHotSpot(e.pos() - self.rect().topLeft())</span><br><span class="line"></span><br><span class="line">        dropAction = drag.exec_(Qt.MoveAction)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">mousePressEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        <span class="built_in">super</span>().mousePressEvent(e)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> e.button() == Qt.LeftButton:</span><br><span class="line">            print(<span class="string">&#x27;按我嘎哈&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.setAcceptDrops(<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">        self.button = Button(<span class="string">&#x27;来吧！！！&#x27;</span>, self)</span><br><span class="line">        self.button.move(<span class="number">100</span>, <span class="number">65</span>)</span><br><span class="line"></span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;点击还能挪&#x27;</span>)</span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">280</span>, <span class="number">150</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">dragEnterEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        e.accept()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">dropEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        position = e.pos()</span><br><span class="line">        self.button.move(position)</span><br><span class="line"></span><br><span class="line">        e.setDropAction(Qt.MoveAction)</span><br><span class="line">        e.accept()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    ex.show()</span><br><span class="line">    app.exec_()</span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">拖拽</span></span><br><span class="line"><span class="string">在GUI里，拖放是指用户点击一个虚拟的对象，拖动，然后放置到另外一个对象上面的动作。</span></span><br><span class="line"><span class="string">一般情况下，需要调用很多动作和方法，创建很多变量。</span></span><br><span class="line"><span class="string">拖放能让用户很直观的操作很复杂的逻辑。</span></span><br><span class="line"><span class="string">一般情况下，我们可以拖放两种东西：数据和图形界面。</span></span><br><span class="line"><span class="string">把一个图像从一个应用拖放到另外一个应用上的实质是操作二进制数据。</span></span><br><span class="line"><span class="string">把一个表格从Firefox上拖放到另外一个位置 的实质是操作一个图形组。</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br></pre></td></tr></table></figure><h1 id="绘图"><a href="#绘图" class="headerlink" title="绘图"></a>绘图</h1><h3 id="33-文本的涂鸦-这个好玩哈"><a href="#33-文本的涂鸦-这个好玩哈" class="headerlink" title="33 文本的涂鸦(这个好玩哈)"></a>33 文本的涂鸦(这个好玩哈)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPainter, QColor, QFont</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.text = <span class="string">&quot;涂鸦要涂的有灵魂&quot;</span></span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">280</span>, <span class="number">170</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;绘画板&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">paintEvent</span>(<span class="params">self, event</span>):</span></span><br><span class="line"></span><br><span class="line">        qp = QPainter()</span><br><span class="line">        qp.begin(self)</span><br><span class="line">        self.drawText(event, qp,<span class="number">168</span>, <span class="number">34</span>, <span class="number">243</span>)</span><br><span class="line">        qp.end()</span><br><span class="line"></span><br><span class="line">        <span class="comment"># qp1 = QPainter()</span></span><br><span class="line">        <span class="comment"># qp1.begin(self)</span></span><br><span class="line">        <span class="comment"># self.drawText(event, qp1,168, 34, 23)</span></span><br><span class="line">        <span class="comment"># qp1.end()</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">drawText</span>(<span class="params">self, event, qp, r,g,b</span>):</span></span><br><span class="line"></span><br><span class="line">        qp.setPen(QColor(r,g,b))</span><br><span class="line">        qp.setFont(QFont(<span class="string">&#x27;微软雅黑&#x27;</span>, <span class="number">15</span>))</span><br><span class="line">        qp.drawText(event.rect(), Qt.AlignCenter, self.text)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="34-点的绘画"><a href="#34-点的绘画" class="headerlink" title="34 点的绘画"></a>34 点的绘画</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPainter</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">import</span> sys, random</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">300</span>, <span class="number">190</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;一大堆点点儿&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">paintEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        qp = QPainter()</span><br><span class="line">        qp.begin(self)</span><br><span class="line">        self.drawPoints(qp)</span><br><span class="line">        qp.end()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">drawPoints</span>(<span class="params">self, qp</span>):</span></span><br><span class="line"></span><br><span class="line">        qp.setPen(Qt.red)</span><br><span class="line">        size = self.size()</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1000</span>):</span><br><span class="line">            x = random.randint(<span class="number">1</span>, size.width()-<span class="number">1</span>)</span><br><span class="line">            y = random.randint(<span class="number">1</span>, size.height()-<span class="number">1</span>)</span><br><span class="line">            qp.drawPoint(x, y)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="35-颜色"><a href="#35-颜色" class="headerlink" title="35 颜色"></a>35 颜色</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPainter, QColor, QBrush</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">350</span>, <span class="number">100</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Colours&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">paintEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        qp = QPainter()</span><br><span class="line">        qp.begin(self)</span><br><span class="line">        self.drawRectangles(qp)</span><br><span class="line">        qp.end()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">drawRectangles</span>(<span class="params">self, qp</span>):</span></span><br><span class="line"></span><br><span class="line">        col = QColor(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>)</span><br><span class="line">        col.setNamedColor(<span class="string">&#x27;#d4d4d4&#x27;</span>)</span><br><span class="line">        qp.setPen(col)</span><br><span class="line"></span><br><span class="line">        qp.setBrush(QColor(<span class="number">200</span>, <span class="number">0</span>, <span class="number">0</span>))</span><br><span class="line">        qp.drawRect(<span class="number">10</span>, <span class="number">15</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        qp.setBrush(QColor(<span class="number">255</span>, <span class="number">80</span>, <span class="number">0</span>, <span class="number">160</span>))</span><br><span class="line">        qp.drawRect(<span class="number">130</span>, <span class="number">15</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        qp.setBrush(QColor(<span class="number">25</span>, <span class="number">0</span>, <span class="number">90</span>, <span class="number">200</span>))</span><br><span class="line">        qp.drawRect(<span class="number">250</span>, <span class="number">15</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="36-QPen是笔么"><a href="#36-QPen是笔么" class="headerlink" title="36 QPen是笔么"></a>36 QPen是笔么</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPainter, QPen</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">280</span>, <span class="number">270</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Pen styles&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">paintEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        qp = QPainter()</span><br><span class="line">        qp.begin(self)</span><br><span class="line">        self.drawLines(qp)</span><br><span class="line">        qp.end()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">drawLines</span>(<span class="params">self, qp</span>):</span></span><br><span class="line"></span><br><span class="line">        pen = QPen(Qt.black, <span class="number">2</span>, Qt.SolidLine)</span><br><span class="line"></span><br><span class="line">        qp.setPen(pen)</span><br><span class="line">        qp.drawLine(<span class="number">20</span>, <span class="number">40</span>, <span class="number">250</span>, <span class="number">40</span>)</span><br><span class="line"></span><br><span class="line">        pen.setStyle(Qt.DashLine)</span><br><span class="line">        qp.setPen(pen)</span><br><span class="line">        qp.drawLine(<span class="number">20</span>, <span class="number">80</span>, <span class="number">250</span>, <span class="number">80</span>)</span><br><span class="line"></span><br><span class="line">        pen.setStyle(Qt.DashDotLine)</span><br><span class="line">        qp.setPen(pen)</span><br><span class="line">        qp.drawLine(<span class="number">20</span>, <span class="number">120</span>, <span class="number">250</span>, <span class="number">120</span>)</span><br><span class="line"></span><br><span class="line">        pen.setStyle(Qt.DotLine)</span><br><span class="line">        qp.setPen(pen)</span><br><span class="line">        qp.drawLine(<span class="number">20</span>, <span class="number">160</span>, <span class="number">250</span>, <span class="number">160</span>)</span><br><span class="line"></span><br><span class="line">        pen.setStyle(Qt.DashDotDotLine)</span><br><span class="line">        qp.setPen(pen)</span><br><span class="line">        qp.drawLine(<span class="number">20</span>, <span class="number">200</span>, <span class="number">250</span>, <span class="number">200</span>)</span><br><span class="line"></span><br><span class="line">        pen.setStyle(Qt.CustomDashLine)</span><br><span class="line">        pen.setDashPattern([<span class="number">1</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">4</span>])</span><br><span class="line">        qp.setPen(pen)</span><br><span class="line">        qp.drawLine(<span class="number">20</span>, <span class="number">240</span>, <span class="number">250</span>, <span class="number">240</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="37-QBrush是啥"><a href="#37-QBrush是啥" class="headerlink" title="37 QBrush是啥?"></a>37 QBrush是啥?</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPainter, QBrush</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">355</span>, <span class="number">280</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Brushes&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">paintEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        qp = QPainter()</span><br><span class="line">        qp.begin(self)</span><br><span class="line">        self.drawBrushes(qp)</span><br><span class="line">        qp.end()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">drawBrushes</span>(<span class="params">self, qp</span>):</span></span><br><span class="line"></span><br><span class="line">        brush = QBrush(Qt.SolidPattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">10</span>, <span class="number">15</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        brush.setStyle(Qt.Dense1Pattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">130</span>, <span class="number">15</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        brush.setStyle(Qt.Dense2Pattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">250</span>, <span class="number">15</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        brush.setStyle(Qt.DiagCrossPattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">10</span>, <span class="number">105</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        brush.setStyle(Qt.Dense5Pattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">130</span>, <span class="number">105</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        brush.setStyle(Qt.Dense6Pattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">250</span>, <span class="number">105</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        brush.setStyle(Qt.HorPattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">10</span>, <span class="number">195</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        brush.setStyle(Qt.VerPattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">130</span>, <span class="number">195</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line">        brush.setStyle(Qt.BDiagPattern)</span><br><span class="line">        qp.setBrush(brush)</span><br><span class="line">        qp.drawRect(<span class="number">250</span>, <span class="number">195</span>, <span class="number">90</span>, <span class="number">60</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="38-贝赛尔曲线-这个学过PS的都知道"><a href="#38-贝赛尔曲线-这个学过PS的都知道" class="headerlink" title="38 贝赛尔曲线(这个学过PS的都知道)"></a>38 贝赛尔曲线(这个学过PS的都知道)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPainter, QPainterPath</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 用QPainterPath路径创建贝塞尔曲线。</span></span><br><span class="line">        <span class="comment"># 使用cubicTo()方法生成，分别需要三个点：起始点，控制点和终止点。</span></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">380</span>, <span class="number">250</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;绘制贝塞尔曲线&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">paintEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line">        qp = QPainter()</span><br><span class="line">        qp.begin(self)</span><br><span class="line">        qp.setRenderHint(QPainter.Antialiasing)</span><br><span class="line">        self.drawBezierCurve(qp)</span><br><span class="line">        qp.end()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">drawBezierCurve</span>(<span class="params">self, qp</span>):</span></span><br><span class="line">        path = QPainterPath()</span><br><span class="line">        path.moveTo(<span class="number">30</span>, <span class="number">30</span>)</span><br><span class="line">        path.cubicTo(<span class="number">30</span>, <span class="number">30</span>, <span class="number">350</span>, <span class="number">30</span>, <span class="number">200</span>, <span class="number">150</span>)</span><br><span class="line"></span><br><span class="line">        qp.drawPath(path)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="39自定义组件"><a href="#39自定义组件" class="headerlink" title="39自定义组件"></a>39自定义组件</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> (QWidget, QSlider, QApplication,</span><br><span class="line">    QHBoxLayout, QVBoxLayout)</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtCore <span class="keyword">import</span> QObject, Qt, pyqtSignal</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtGui <span class="keyword">import</span> QPainter, QFont, QColor, QPen</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Communicate</span>(<span class="params">QObject</span>):</span></span><br><span class="line"></span><br><span class="line">    updateBW = pyqtSignal(<span class="built_in">int</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BurningWidget</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.setMinimumSize(<span class="number">1</span>, <span class="number">30</span>)</span><br><span class="line">        self.value = <span class="number">75</span></span><br><span class="line">        self.num = [<span class="number">75</span>, <span class="number">150</span>, <span class="number">225</span>, <span class="number">300</span>, <span class="number">375</span>, <span class="number">450</span>, <span class="number">525</span>, <span class="number">600</span>, <span class="number">675</span>]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">setValue</span>(<span class="params">self, value</span>):</span></span><br><span class="line"></span><br><span class="line">        self.value = value</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">paintEvent</span>(<span class="params">self, e</span>):</span></span><br><span class="line"></span><br><span class="line">        qp = QPainter()</span><br><span class="line">        qp.begin(self)</span><br><span class="line">        self.drawWidget(qp)</span><br><span class="line">        qp.end()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">drawWidget</span>(<span class="params">self, qp</span>):</span></span><br><span class="line"></span><br><span class="line">        MAX_CAPACITY = <span class="number">700</span></span><br><span class="line">        OVER_CAPACITY = <span class="number">750</span></span><br><span class="line"></span><br><span class="line">        font = QFont(<span class="string">&#x27;Serif&#x27;</span>, <span class="number">7</span>, QFont.Light)</span><br><span class="line">        qp.setFont(font)</span><br><span class="line"></span><br><span class="line">        size = self.size()</span><br><span class="line">        w = size.width()</span><br><span class="line">        h = size.height()</span><br><span class="line"></span><br><span class="line">        step = <span class="built_in">int</span>(<span class="built_in">round</span>(w / <span class="number">10</span>))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        till = <span class="built_in">int</span>(((w / OVER_CAPACITY) * self.value))</span><br><span class="line">        full = <span class="built_in">int</span>(((w / OVER_CAPACITY) * MAX_CAPACITY))</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> self.value &gt;= MAX_CAPACITY:</span><br><span class="line"></span><br><span class="line">            qp.setPen(QColor(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>))</span><br><span class="line">            qp.setBrush(QColor(<span class="number">255</span>, <span class="number">255</span>, <span class="number">184</span>))</span><br><span class="line">            qp.drawRect(<span class="number">0</span>, <span class="number">0</span>, full, h)</span><br><span class="line">            qp.setPen(QColor(<span class="number">255</span>, <span class="number">175</span>, <span class="number">175</span>))</span><br><span class="line">            qp.setBrush(QColor(<span class="number">255</span>, <span class="number">175</span>, <span class="number">175</span>))</span><br><span class="line">            qp.drawRect(full, <span class="number">0</span>, till-full, h)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line"></span><br><span class="line">            qp.setPen(QColor(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>))</span><br><span class="line">            qp.setBrush(QColor(<span class="number">255</span>, <span class="number">255</span>, <span class="number">184</span>))</span><br><span class="line">            qp.drawRect(<span class="number">0</span>, <span class="number">0</span>, till, h)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        pen = QPen(QColor(<span class="number">20</span>, <span class="number">20</span>, <span class="number">20</span>), <span class="number">1</span>,</span><br><span class="line">            Qt.SolidLine)</span><br><span class="line"></span><br><span class="line">        qp.setPen(pen)</span><br><span class="line">        qp.setBrush(Qt.NoBrush)</span><br><span class="line">        qp.drawRect(<span class="number">0</span>, <span class="number">0</span>, w-<span class="number">1</span>, h-<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">        j = <span class="number">0</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(step, <span class="number">10</span>*step, step):</span><br><span class="line"></span><br><span class="line">            qp.drawLine(i, <span class="number">0</span>, i, <span class="number">5</span>)</span><br><span class="line">            metrics = qp.fontMetrics()</span><br><span class="line">            fw = metrics.width(<span class="built_in">str</span>(self.num[j]))</span><br><span class="line">            qp.drawText(i-fw/<span class="number">2</span>, h/<span class="number">2</span>, <span class="built_in">str</span>(self.num[j]))</span><br><span class="line">            j = j + <span class="number">1</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Example</span>(<span class="params">QWidget</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        OVER_CAPACITY = <span class="number">750</span></span><br><span class="line"></span><br><span class="line">        sld = QSlider(Qt.Horizontal, self)</span><br><span class="line">        sld.setFocusPolicy(Qt.NoFocus)</span><br><span class="line">        sld.setRange(<span class="number">1</span>, OVER_CAPACITY)</span><br><span class="line">        sld.setValue(<span class="number">75</span>)</span><br><span class="line">        sld.setGeometry(<span class="number">30</span>, <span class="number">40</span>, <span class="number">150</span>, <span class="number">30</span>)</span><br><span class="line"></span><br><span class="line">        self.c = Communicate()</span><br><span class="line">        self.wid = BurningWidget()</span><br><span class="line">        self.c.updateBW[<span class="built_in">int</span>].connect(self.wid.setValue)</span><br><span class="line"></span><br><span class="line">        sld.valueChanged[<span class="built_in">int</span>].connect(self.changeValue)</span><br><span class="line">        hbox = QHBoxLayout()</span><br><span class="line">        hbox.addWidget(self.wid)</span><br><span class="line">        vbox = QVBoxLayout()</span><br><span class="line">        vbox.addStretch(<span class="number">1</span>)</span><br><span class="line">        vbox.addLayout(hbox)</span><br><span class="line">        self.setLayout(vbox)</span><br><span class="line"></span><br><span class="line">        self.setGeometry(<span class="number">300</span>, <span class="number">300</span>, <span class="number">390</span>, <span class="number">210</span>)</span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;Burning widget&#x27;</span>)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">changeValue</span>(<span class="params">self, value</span>):</span></span><br><span class="line"></span><br><span class="line">        self.c.updateBW.emit(value)</span><br><span class="line">        self.wid.repaint()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line"></span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = Example()</span><br><span class="line">    sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><p>终于翻到底部了,能看到这里,给你自己一个奖励吧!!!</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">       ┌─┐       ┌─┐ + +</span></span><br><span class="line"><span class="string">    ┌──┘ ┴───────┘ ┴──┐++</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    │       ───       │++ + + +</span></span><br><span class="line"><span class="string">    ███████───███████ │+</span></span><br><span class="line"><span class="string">    │                 │+</span></span><br><span class="line"><span class="string">    │       ─┴─       │</span></span><br><span class="line"><span class="string">    │                 │</span></span><br><span class="line"><span class="string">    └───┐         ┌───┘</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         │   + +</span></span><br><span class="line"><span class="string">        │         │</span></span><br><span class="line"><span class="string">        │         └──────────────┐</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        │                        ├─┐</span></span><br><span class="line"><span class="string">        │                        ┌─┘</span></span><br><span class="line"><span class="string">        │                        │</span></span><br><span class="line"><span class="string">        └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +</span></span><br><span class="line"><span class="string">          │ ─┤ ─┤       │ ─┤ ─┤</span></span><br><span class="line"><span class="string">          └──┴──┘       └──┴──┘  + + + +</span></span><br><span class="line"><span class="string">                 神兽保佑</span></span><br><span class="line"><span class="string">                代码无BUG!</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> summer </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> PyQt5 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PyQt5学习笔记1-5</title>
      <link href="python/GUI/pyqt5/note/pyqt5-note1-5/"/>
      <url>python/GUI/pyqt5/note/pyqt5-note1-5/</url>
      
        <content type="html"><![CDATA[<h1 id="PyQt5的第一课-环境的准备"><a href="#PyQt5的第一课-环境的准备" class="headerlink" title="PyQt5的第一课-环境的准备"></a>PyQt5的第一课-环境的准备</h1><p>一个牛人的博客-&gt;<a href="http://bcczcs.com/blog/">编程创造城市</a></p><p>学什么Java,Python它不香么?</p><p>pyqt5,我来了</p><p>学习pyqt5中遇到的问题汇总</p><p><a href="https://blog.csdn.net/proplume/article/details/88145115">python3.6：DLL load failed:找不到指定的模块（from PyQt5 import QtCore）</a></p><h3 id="环境的准备"><a href="#环境的准备" class="headerlink" title="环境的准备"></a>环境的准备</h3><p>anaconda3+pycharm+pyqt5</p><p>这个方式没准备好</p><p>所以我用的组合是</p><p>UIC用python3.7的,qtdesigner用的是anaconda3中的</p><p>清华大学开源镜像站,这个贼JB快(<a href="https://pypi.tuna.tsinghua.edu.cn/simple/">https://pypi.tuna.tsinghua.edu.cn/simple/</a>)</p><p>国内清华的镜像安装pyqt5</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple</span><br></pre></td></tr></table></figure><p>国内清华的镜像安装pyqt5-tools</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install pyqt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple</span><br></pre></td></tr></table></figure><p>安装完成之后需要在pycharm中配置两个扩展工具</p><h3 id="QTdesigner"><a href="#QTdesigner" class="headerlink" title="QTdesigner"></a>QTdesigner</h3><ul><li>name:QTdesigner</li><li>Program:<code>E:\Python37\Lib\site-packages\pyqt5_tools\Qt\bin\designer.exe</code></li><li>Working directory:<code>$FileDir$</code></li></ul><h3 id="PyUIC"><a href="#PyUIC" class="headerlink" title="PyUIC"></a>PyUIC</h3><ul><li>name:PyUIC</li><li>Program:<code>E:\Python37\python.exe</code></li><li>Arguments:<code>-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py</code></li><li>Working directory:<code>$FileDir$</code></li></ul><h1 id="PyQt5的第二课-hellopyqt5"><a href="#PyQt5的第二课-hellopyqt5" class="headerlink" title="PyQt5的第二课-hellopyqt5"></a>PyQt5的第二课-hellopyqt5</h1><h3 id="使用QtWidgets写第一个程序-基于pyqt5"><a href="#使用QtWidgets写第一个程序-基于pyqt5" class="headerlink" title="使用QtWidgets写第一个程序,基于pyqt5"></a>使用QtWidgets写第一个程序,基于pyqt5</h3><ul><li>使用纯代码写第一个PyQt5程序</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span>  QApplication, QWidget</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    w = QWidget()</span><br><span class="line">    w.resize(<span class="number">400</span>,<span class="number">300</span>)</span><br><span class="line">    w.move(<span class="number">200</span>,<span class="number">300</span>)</span><br><span class="line">    w.setWindowTitle(<span class="string">&quot;刘金玉编程&quot;</span>)</span><br><span class="line">    w.show()</span><br><span class="line">    sys.exit(app.exec())</span><br></pre></td></tr></table></figure><h1 id="PyQt5的第三课-pyqt5与qtdesigner对照分析"><a href="#PyQt5的第三课-pyqt5与qtdesigner对照分析" class="headerlink" title="PyQt5的第三课 - pyqt5与qtdesigner对照分析"></a>PyQt5的第三课 - pyqt5与qtdesigner对照分析</h1><h3 id="空的程序的生成的样子"><a href="#空的程序的生成的样子" class="headerlink" title="空的程序的生成的样子"></a>空的程序的生成的样子</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Form implementation generated from reading ui file &#x27;first.ui&#x27;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># Created by: PyQt5 UI code generator 5.13.0</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># WARNING! All changes made in this file will be lost!</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5 <span class="keyword">import</span> QtCore, QtGui, QtWidgets</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Ui_Form</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">setupUi</span>(<span class="params">self, Form</span>):</span></span><br><span class="line">        Form.setObjectName(<span class="string">&quot;Form&quot;</span>)</span><br><span class="line">        Form.resize(<span class="number">500</span>, <span class="number">300</span>)</span><br><span class="line"></span><br><span class="line">        self.retranslateUi(Form)</span><br><span class="line">        QtCore.QMetaObject.connectSlotsByName(Form)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">retranslateUi</span>(<span class="params">self, Form</span>):</span></span><br><span class="line">        _translate = QtCore.QCoreApplication.translate</span><br><span class="line">        Form.setWindowTitle(_translate(<span class="string">&quot;Form&quot;</span>, <span class="string">&quot;Form&quot;</span>))</span><br><span class="line">```      </span><br><span class="line"> </span><br><span class="line">```python</span><br><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by 秋叶夏风</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;pyqt5主模块&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入python系统类库</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入pyqt5类用到的类库,QApplication应用程序类,Qwidget控件的基类</span></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication,QWidget</span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入生成界面类的模块</span></span><br><span class="line"><span class="keyword">import</span> first</span><br><span class="line"></span><br><span class="line"><span class="comment"># 这回不写main了</span></span><br><span class="line"><span class="comment"># 直接就实例化一个类,通过构造函数传入一个python的应用参数</span></span><br><span class="line">print(sys.argv) <span class="comment"># 这里打印出包含当前文件绝对路径名称的列表</span></span><br><span class="line"><span class="comment"># sys.argv就是自己的文件名称的列表</span></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 实例化界面基类</span></span><br><span class="line">w = QWidget()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 实例化生成的界面的类</span></span><br><span class="line">form = first.Ui_Form()</span><br><span class="line"><span class="comment"># 将生成的窗体控件及配置载入到w控件对象汇总</span></span><br><span class="line">form.setupUi(w)</span><br><span class="line"><span class="comment"># 使用窗体显示</span></span><br><span class="line">w.show()</span><br><span class="line"><span class="comment"># app.exec_()表示程序界面监听事件的开始,是一个死循环</span></span><br><span class="line"><span class="comment"># 这里说白了是一个死循环,就像tkinter中的loop一样</span></span><br><span class="line">sys.exit(app.exec_())</span><br></pre></td></tr></table></figure><h3 id="QT-Designer-设计师界面"><a href="#QT-Designer-设计师界面" class="headerlink" title="QT Designer 设计师界面"></a>QT Designer 设计师界面</h3><h5 id="Geometry属性"><a href="#Geometry属性" class="headerlink" title="Geometry属性"></a>Geometry属性</h5><ul><li>X:代表窗体出现的位置是在屏幕的左上角水平方向0的位置</li><li>Y:代表窗体出现的位置是在屏幕的左上角垂直方向0的位置</li><li>宽度:窗体宽度(单位像素)</li><li>高度:窗体高度(单位像素)</li></ul><h5 id="ObjectName属性"><a href="#ObjectName属性" class="headerlink" title="ObjectName属性"></a>ObjectName属性</h5><p>表示窗体对象的名称,对应到python代码中设置窗体名称的方法<br>setObjectName</p><ul><li>窗体对象其实就是指QtWidgets的实例化对象</li></ul><h3 id="补充PyUIC命令解析"><a href="#补充PyUIC命令解析" class="headerlink" title="补充PyUIC命令解析"></a>补充PyUIC命令解析</h3><ul><li><p>使用python.exe解释器</p></li><li><p>-mPyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py</p></li><li><p>说明: -m表示调用某个模块,这里表示调用PyQt5.uic.pyuic模块</p></li><li><p> $FileName$ 表示需要转换的源文件名称</p></li><li><p>o 表示需要生成目标文件,这里使用$FileNameWithoutExtension$表示与源文件相同的文件名称,但是不包含扩展名的目标文件,扩展名,我们通过自己连接.py,最终表示生成的python类型的文件</p></li></ul><h3 id="Resize函数"><a href="#Resize函数" class="headerlink" title="Resize函数"></a>Resize函数</h3><ul><li>作用:重新调整大小</li><li>有两个参数,第一个参数表示宽度值,第二个参数表示高度值</li><li>举例:form.resize(300,400)</li></ul><h3 id="Move函数"><a href="#Move函数" class="headerlink" title="Move函数"></a>Move函数</h3><ul><li>作用:调整窗体的位置</li><li>第一个参数表示水平方向的位置</li><li>第二个参数表示垂直方向的位置</li></ul><h3 id="Qt中信号的理解-说白了就像js中的事件"><a href="#Qt中信号的理解-说白了就像js中的事件" class="headerlink" title="Qt中信号的理解(说白了就像js中的事件)"></a>Qt中信号的理解(说白了就像js中的事件)</h3><p>比如说单击事件,某个超时信号等都是qt中的信号,说到底其实就是界面上面发生了某个事件</p><h3 id="绝对路径"><a href="#绝对路径" class="headerlink" title="绝对路径"></a>绝对路径</h3><ul><li>绝对路径:从根目录开始的路径</li><li>相对路径:相对于某个文件目录的路径</li><li>相对路径往往有一些符号代表:<br>.点表示当前路径<br>.. 表示上一层路径<br>../../上一层的上一层</li></ul><h3 id="show函数"><a href="#show函数" class="headerlink" title="show函数"></a>show函数</h3><ul><li>pyqt5中的show函数的将窗体显示出来</li></ul><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul><li><p> 掌握qtdesigner设计界面与pyuic转换后文件代码的对应关系</p></li><li><p> 掌握pyqt5中界面中常用函数的基本用法</p></li><li><p>掌握如何调用生成界面的思想.实则是如何使用pyqt5纯代码写GUI界面的关键.</p></li></ul><h1 id="PyQt5的第四课-pyqt5设置窗体图标"><a href="#PyQt5的第四课-pyqt5设置窗体图标" class="headerlink" title="PyQt5的第四课 - pyqt5设置窗体图标"></a>PyQt5的第四课 - pyqt5设置窗体图标</h1><p>在pyqt5之前,有pyqt1234不同的版本,我们直接学习pyqt5就行了</p><p>pyqt4和pyqt5不互相兼容</p><p>现在pyqt4已经放弃开发了</p><h3 id="知识回顾"><a href="#知识回顾" class="headerlink" title="知识回顾"></a>知识回顾</h3><ol><li>纯pyqt5代码来创建窗体程序</li><li>掌握理解GUI窗体的开发原理</li></ol><h3 id="python的纯代码编写GUI"><a href="#python的纯代码编写GUI" class="headerlink" title="python的纯代码编写GUI"></a>python的纯代码编写GUI</h3><p>最简单代码</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication,QWidget</span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">w = QWidget()</span><br><span class="line">w.show()</span><br><span class="line">app.exec_()</span><br></pre></td></tr></table></figure><h3 id="pyqt5设置窗体图标"><a href="#pyqt5设置窗体图标" class="headerlink" title="pyqt5设置窗体图标"></a>pyqt5设置窗体图标</h3><ul><li>使用函数setWindowIcon函数</li><li>设置图标需要类库的导入from PyQt5.QtGui import Qicon</li><li>将Qicon类利用构造函数进行初始化</li></ul><h3 id="图标到哪里下载"><a href="#图标到哪里下载" class="headerlink" title="图标到哪里下载?"></a>图标到哪里下载?</h3><ul><li>阿里巴巴图标库</li><li><a href="https://www.iconfont.cn/">https://www.iconfont.cn</a></li><li>注意:下载图标尽量采用png或者gif格式,可以背景透明</li><li>在项目中,我们往往会把所有的图标放到同一个文件夹中,然后通过相同路径进行调用.</li></ul><h3 id="QWidget中设置图标与QApplication中设置图标的区别"><a href="#QWidget中设置图标与QApplication中设置图标的区别" class="headerlink" title="QWidget中设置图标与QApplication中设置图标的区别"></a>QWidget中设置图标与QApplication中设置图标的区别</h3><ul><li><p>通过QWidget设置出来的窗体的图标,可以是每个窗体一个图标.</p></li><li><p>通过QApplication的<code>setWindowIcon(QIcon(&quot;./img/水枪.png&quot;))</code><br>设置所有的窗体的默认图标</p></li><li><p>注意:在mac系统中只能识别QApplication中设置的图标</p></li></ul><h3 id="总结强调"><a href="#总结强调" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>1.掌握基本的pyqt5纯代码编写GUI</li><li>2.设置窗体的图标</li><li>3.理解QApplication和QWidget设置图标的哟啥不一样的地方</li></ul><h1 id="PyQt5的第五课-pyqt5显示提示框"><a href="#PyQt5的第五课-pyqt5显示提示框" class="headerlink" title="PyQt5的第五课 - pyqt5显示提示框"></a>PyQt5的第五课 - pyqt5显示提示框</h1><h3 id="知识回顾-1"><a href="#知识回顾-1" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li> 利用pyqt5纯代码编写第一个程序</li><li> 掌握了程序图标的设置方法</li></ul><h3 id="最基本的pyqt5代码"><a href="#最基本的pyqt5代码" class="headerlink" title="最基本的pyqt5代码"></a>最基本的pyqt5代码</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QApplication,QWidget</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">w = QWidget()</span><br><span class="line">w.show()</span><br><span class="line">app.exec_()</span><br></pre></td></tr></table></figure><h3 id="显示提示框"><a href="#显示提示框" class="headerlink" title="显示提示框"></a>显示提示框</h3><ul><li>使用函数setToolTip<br>注意:基本上所有的控件,包括窗体都有setToolTip这个函数,这个函数基本上都有</li></ul><p>使用格式:<br>    控件对象setToolTip(这里是需要提示的字符串)</p><h3 id="按钮控件"><a href="#按钮控件" class="headerlink" title="按钮控件"></a>按钮控件</h3><ul><li>使用类QPushButton</li><li>基本使用:实例化一个按钮举例<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 按钮</span><br><span class="line">btn &#x3D; QPushButton(&quot;老刘&quot;,w)</span><br></pre></td></tr></table></figure></li><li>格式:</li><li>声明定义一个实例化对象 的名称 = QPushButton(按钮文字,父容器)</li></ul><h3 id="系统中文件查找技巧"><a href="#系统中文件查找技巧" class="headerlink" title="系统中文件查找技巧"></a>系统中文件查找技巧</h3><ul><li>我们可以搜索包含<code>*ToolTip*</code>这个关键字的文件,直接搜索,搜不到,在两边加上<code>*</code>就能进行模糊搜索</li></ul><h3 id="如何找到类"><a href="#如何找到类" class="headerlink" title="如何找到类"></a>如何找到类</h3><ul><li><p> 我们可以通过pycharm上面代码右键找到对应的pyqt5的文件安装所在位置</p></li><li><p> 利用模糊查找到我们需要的类所在的pyqt5中的位置</p></li><li><p> 到程序中导入找到的类</p></li></ul><h3 id="显示框文字样式设置"><a href="#显示框文字样式设置" class="headerlink" title="显示框文字样式设置"></a>显示框文字样式设置</h3><ul><li><p> 需要导入QToolTip类库</p></li><li><p> 通过QToolTip的setFont方法设置文字样式</p></li><li><p> 需要导入Qfont类库</p></li><li><p> 实例化QFont类进行文字样式设置</p></li><li><p> 这个显示设置,是在全局样式上面显示提示效果的,说白了就是先显示后设置也好使</p></li></ul><h3 id="总结强调-1"><a href="#总结强调-1" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li><p> 掌握基础pyqt5代码GUI编写</p></li><li><p> 掌握显示框设置setToolTip函数</p></li><li><p> 掌握显示框文字样式设置</p></li><li><p> 掌握代码编写思路</p></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> PyQt5 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PyQt5学习笔记6-10</title>
      <link href="python/GUI/pyqt5/note/pyqt5-note6-10/"/>
      <url>python/GUI/pyqt5/note/pyqt5-note6-10/</url>
      
        <content type="html"><![CDATA[<h1 id="PyQt5的第六课-PyQt5类的封装"><a href="#PyQt5的第六课-PyQt5类的封装" class="headerlink" title="PyQt5的第六课 - PyQt5类的封装"></a>PyQt5的第六课 - PyQt5类的封装</h1><h3 id="知识回顾"><a href="#知识回顾" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>掌握纯代码写pyqt5程序</li><li>显示提示框tooltip功能(这个玩意在所有的控件中都是存在的)</li></ul><h3 id="代码封装思路"><a href="#代码封装思路" class="headerlink" title="代码封装思路"></a>代码封装思路</h3><ul><li>分析哪些代码需要封装:需要封装的就是我们对窗体配置的代码</li><li>利用类的继承特性</li><li>调用父类Qwidget的构造方法<code>super().__init__()</code></li><li>调用自己的构造方法</li></ul><h3 id="用类的方式去实现空的窗口的代码"><a href="#用类的方式去实现空的窗口的代码" class="headerlink" title="用类的方式去实现空的窗口的代码"></a>用类的方式去实现空的窗口的代码</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget,QApplication</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyClass</span>(<span class="params">QWidget</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.setWindowTitle(<span class="string">&quot;刘金玉编程&quot;</span>)</span><br><span class="line">        self.setGeometry(<span class="number">30</span>,<span class="number">40</span>,<span class="number">300</span>,<span class="number">200</span>)</span><br><span class="line">        self.show()</span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    c = MyClass()</span><br><span class="line">    app.exec_()</span><br></pre></td></tr></table></figure><h3 id="GUI位置大小函数setGeometry"><a href="#GUI位置大小函数setGeometry" class="headerlink" title="GUI位置大小函数setGeometry"></a>GUI位置大小函数setGeometry</h3><ul><li>这个函数相当于resize函数和remove函数功能的合体</li><li>函数使用格式:<br>  控件对象.setGeometry(X轴,Y轴,宽度,高度)</li></ul><h3 id="信号"><a href="#信号" class="headerlink" title="信号"></a>信号</h3><ul><li>窗体上的信号被app.exec_()死循环监听着.</li><li>信号至少在QT中针对某个发生的时间的说法</li><li>槽是QT中发生的具体的某个时间,就是槽</li><li>窗体上的对GUI界面操作行为都是被监听着的</li><li>GUI是被事件驱动的</li></ul><h3 id="信号槽的简单使用"><a href="#信号槽的简单使用" class="headerlink" title="信号槽的简单使用"></a>信号槽的简单使用</h3><ul><li>格式:信号源.信号.connect(槽)</li><li>格式解释:信号源(按钮)信号(clicked).connet(某个事件方法)</li><li>注意:在绑定信号槽的过程汇总,我们的槽方法可以不加括号的,传递的是方法的引用本身<br>说白了,我要的是函数,而不是函数的返回值,这里如果想要加上参数,就用lambda 吧!</li></ul><h3 id="加入了按钮的点击关闭时间的代码"><a href="#加入了按钮的点击关闭时间的代码" class="headerlink" title="加入了按钮的点击关闭时间的代码"></a>加入了按钮的点击关闭时间的代码</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QWidget, QApplication, QPushButton</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyClass</span>(<span class="params">QWidget</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.setWindowTitle(<span class="string">&quot;刘金玉编程&quot;</span>)</span><br><span class="line">        self.setGeometry(<span class="number">30</span>,<span class="number">40</span>,<span class="number">300</span>,<span class="number">200</span>)</span><br><span class="line">        btn = QPushButton(<span class="string">&quot;关闭&quot;</span>,self)</span><br><span class="line">        btn.move(<span class="number">5</span>,<span class="number">6</span>)</span><br><span class="line">        <span class="comment"># 将信号发送到一个槽</span></span><br><span class="line">        <span class="comment"># 设置按钮的点击后关闭窗体的时间</span></span><br><span class="line">        btn.clicked.connect(self.close)</span><br><span class="line">        self.show()</span><br><span class="line"></span><br><span class="line">app = QApplication(sys.argv)</span><br><span class="line">c = MyClass()</span><br><span class="line">app.exec_()</span><br></pre></td></tr></table></figure><h3 id="总结强调"><a href="#总结强调" class="headerlink" title="总结强调"></a>总结强调</h3><ol><li>掌握类的继承QWidget的基本思想</li><li>掌握类的功能封装</li><li>掌握setGeometry函数</li><li>掌握简单的信号槽的使用</li></ol><h1 id="PyQt5的第七课-PyQt5消息盒子QMessageBox"><a href="#PyQt5的第七课-PyQt5消息盒子QMessageBox" class="headerlink" title="PyQt5的第七课 - PyQt5消息盒子QMessageBox"></a>PyQt5的第七课 - PyQt5消息盒子QMessageBox</h1><h3 id="知识回顾-1"><a href="#知识回顾-1" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>使用类进行pyqt5的GUI开发封装</li><li>使用setGeometry哈数:大小,位置</li><li>掌握类的继承与内部屌用</li></ul><h3 id="消息盒子"><a href="#消息盒子" class="headerlink" title="消息盒子"></a>消息盒子</h3><ul><li>使用类库QMessageBox</li><li>不同的图标的消息类别:</li><li>带有图标的消息盒子setGeometry,图标可以是问号question,信息information</li></ul><p>-注意:使用消息盒子后,最后会返回一个按钮类型的结果,最后这个结果是我们人机交互的结果</p><p>点击按钮出现消息选择框,处理消息选择框的结果<br>基础类封装的代码</p><h3 id="重写关闭事件-思路"><a href="#重写关闭事件-思路" class="headerlink" title="重写关闭事件-思路"></a>重写关闭事件-思路</h3><ul><li>当点击关闭按钮的时候,执行的是窗体的关闭,而窗体的关闭,等同于点击窗口的右上角的按钮的效果.这个效果是QWidget基类所实现的</li></ul><p>-提问:我么该如何实现我们自己需要的关闭时候的效果呢?</p><ul><li><p>重写父类方法</p></li><li><p>重新写关闭事件</p><h3 id="QMessageBox使用格式"><a href="#QMessageBox使用格式" class="headerlink" title="QMessageBox使用格式"></a>QMessageBox使用格式</h3><p>使用格式:<br>QMessageBox.question(self,”提示title”,”消息内容”,”默认选中值”)</p></li></ul><h3 id="如何阻止事件的关闭"><a href="#如何阻止事件的关闭" class="headerlink" title="如何阻止事件的关闭"></a>如何阻止事件的关闭</h3><ul><li>利用传过来的时间对象</li><li>我们通过输出形式,看到时间对象的属性和方法,猜测到具体的方法<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Event.accept()<span class="comment">#同意关闭</span></span><br><span class="line">Event.ignore()<span class="comment">#忽略操作</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="总结强调-1"><a href="#总结强调-1" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握的类的封装基本代码</li></ul><h1 id="PyQt5的第八课-PyQt5窗体居中和布局"><a href="#PyQt5的第八课-PyQt5窗体居中和布局" class="headerlink" title="PyQt5的第八课 - PyQt5窗体居中和布局"></a>PyQt5的第八课 - PyQt5窗体居中和布局</h1><h3 id="知识回顾-2"><a href="#知识回顾-2" class="headerlink" title="知识回顾"></a>知识回顾</h3><ol><li>窗体事件的重写,closeEvent事件</li><li>QMessageBox消息框的使用</li></ol><h3 id="窗体的居中"><a href="#窗体的居中" class="headerlink" title="窗体的居中"></a>窗体的居中</h3><ul><li>默认情况下,如果没有添加窗体位置的函数,</li><li>手动调整到屏幕居中位置</li><li>通过desktop()函数阿里获取桌面控件的对象QDesktopWidget</li><li>通过桌面对象的width()函数来获取屏幕的宽度的分辨率</li></ul><h3 id="标签文本控件"><a href="#标签文本控件" class="headerlink" title="标签文本控件"></a>标签文本控件</h3><ul><li>使用类库Qlabel</li><li>使用格式:<br>lbl = QLabel(“编程创造城市”,self)</li></ul><h3 id="绝对布局"><a href="#绝对布局" class="headerlink" title="绝对布局"></a>绝对布局</h3><ul><li>直接通过move()到某个像素点的位置</li><li>特点:非常灵活</li><li>弱点:不能随着窗体的大小而变化</li></ul><h3 id="总结强调-2"><a href="#总结强调-2" class="headerlink" title="总结强调"></a>总结强调</h3><ol><li>掌握窗体居中布局的方法</li><li>掌握利用绝对布局的方法以及优劣势</li></ol><h1 id="PyQt5的第久课-PyQt5窗体绝对布局和相对布局"><a href="#PyQt5的第久课-PyQt5窗体绝对布局和相对布局" class="headerlink" title="PyQt5的第久课 - PyQt5窗体绝对布局和相对布局"></a>PyQt5的第久课 - PyQt5窗体绝对布局和相对布局</h1><h3 id="知识回顾-3"><a href="#知识回顾-3" class="headerlink" title="知识回顾"></a>知识回顾</h3><ol><li><p>点到了窗体的绝对布局</p></li><li><p>窗体的居中方式:根据已知像素,计算窗体的起点位置</p></li></ol><ul><li>Desktop()函数,这个函数是在QApplication类中的.函数返回的结果QDesktopWidget对象</li></ul><ol start="3"><li>标签控件的使用</li></ol><ul><li><p>想要获取水平方向,调用width函数</p></li><li><p>想要获取垂直方向,调用height函数</p></li></ul><h3 id="相对布局"><a href="#相对布局" class="headerlink" title="相对布局"></a>相对布局</h3><ol><li><p>绝对布局是直接将控件载入到窗体的位置就可以了.一般直接采用move函数移动到指定的位置后不变.</p></li><li><p>相对布局是要将控件放到盒布局中.一般是还要加入一个盒布局.QHboxlayout(水平方向) QVboxlayout(垂直方向),网格布局(QgridBoxla yout)</p></li></ol><h3 id="绝对布局与相对布局的不同"><a href="#绝对布局与相对布局的不同" class="headerlink" title="绝对布局与相对布局的不同"></a>绝对布局与相对布局的不同</h3><ul><li>布局中的控件可以随着窗体的变化而变化</li><li>布局中的控件之间的距离可以按照比例来调节</li></ul><h3 id="QHBoxLayout"><a href="#QHBoxLayout" class="headerlink" title="QHBoxLayout"></a>QHBoxLayout</h3><ul><li><p>要是水平盒布局不好记的话,那你看这个H是不是,中间有一个横的</p></li><li><p>把所有的控件只能在水平反向上面排列,会自动一个一个排列不会重叠,这个是一个特性</p></li><li><p>默认情况下,垂直居中的</p></li><li><p>记忆方式:看H中的横线,就认为是水平布局</p></li></ul><h3 id="垂直布局的思想"><a href="#垂直布局的思想" class="headerlink" title="垂直布局的思想"></a>垂直布局的思想</h3><ul><li>增加弹簧</li></ul><h3 id="弹簧"><a href="#弹簧" class="headerlink" title="弹簧"></a>弹簧</h3><ul><li>就是直接使用盒布局的addstretcfh方法就可以了</li><li>Addstretch(弹簧比例)</li><li>弹簧比例:是指在窗体中进行指定的比例分割.</li></ul><h3 id="总结强调-3"><a href="#总结强调-3" class="headerlink" title="总结强调"></a>总结强调</h3><ol><li>掌握相对布局与绝对布局的区别</li><li>掌握兼顾地布局中的水平盒布局与垂直盒布局</li><li>掌握和布局中的控件比例排布关系</li></ol><h1 id="PyQt5的第时课-PyQt5网格布局QGridLayout"><a href="#PyQt5的第时课-PyQt5网格布局QGridLayout" class="headerlink" title="PyQt5的第时课 - PyQt5网格布局QGridLayout"></a>PyQt5的第时课 - PyQt5网格布局QGridLayout</h1><h3 id="知识回顾-4"><a href="#知识回顾-4" class="headerlink" title="知识回顾"></a>知识回顾</h3><ul><li>掌握QHboxLayout水平盒子布局</li><li>掌握QVboxLayout垂直盒子布局</li><li>盒子布局,我们可以结合自带的”弹簧功能”addstrach</li><li>LineEdit类库作用:单行文本框</li></ul><h3 id="网格布局"><a href="#网格布局" class="headerlink" title="网格布局"></a>网格布局</h3><table>    <tr>        <td>0,0</td><td>0,1</td>    </tr>    <tr>        <td>1,0</td><td>1,1</td>    </tr>    <tr>        <td>2,0</td><td>2,1</td>    </tr></table><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">网格布局的使用时需要注意:</span><br><span class="line"><span class="number">1.</span> 要导入类库QGridLayout</span><br><span class="line"><span class="number">2.</span> 该布局的索引默认从<span class="number">0</span>开始</span><br><span class="line"><span class="number">3.</span> 使用网格布局前先要进行类的实例化</span><br></pre></td></tr></table></figure><h3 id="网格布局设置"><a href="#网格布局设置" class="headerlink" title="网格布局设置"></a>网格布局设置</h3><ul><li><p>我们其实可以通过网格布局实例化后的对象,直接通过代码提示的方式看到很多我们可以直接实现的方法.</p></li><li><p>比如:我们想要设置网格之间的空间距离,我们呢可以设置setSpacing来设置,</p></li><li><p>举例:Grid.setSpacing(空间的像素值)</p></li><li><p>我们要学会举一反三,通过set的方式设置其他功能</p></li></ul><h3 id="多行文本框的"><a href="#多行文本框的" class="headerlink" title="多行文本框的"></a>多行文本框的</h3><ul><li>使用QTextEdit这个类库</li><li>使用方法类似于直接对类的实例化</li></ul><h3 id="总结强调-4"><a href="#总结强调-4" class="headerlink" title="总结强调"></a>总结强调</h3><ul><li>掌握网格布局的思想,QGridLayout</li><li>掌握新控件多行文本框的使用</li><li>根据QTDesigner来了解新控件,或者根据pyqt5中提供目录来了解新控件</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> PyQt5 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>IDEA自动生成序列化ID</title>
      <link href="ide/jetbrains/idea/jetbrains-idea-serialID/"/>
      <url>ide/jetbrains/idea/jetbrains-idea-serialID/</url>
      
        <content type="html"><![CDATA[<p>idea是十分智能的Java集成开发环境</p><p>而我们在用实体类继承 java.io.Serializable后，需要设置序列化ID。</p><p>java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时，JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较，如果相同则认为是一致的，便可以进行反序列化，否则就会报序列化版本不一致的异常。</p><p>而IDEA，默认是不支持自动生成序列化ID的（我使用的是IDEA2019版本）。</p><p>今天小编就交大家如何自定义设置自动生成序列化</p><h3 id="1、安装-serialVersionUID-插件："><a href="#1、安装-serialVersionUID-插件：" class="headerlink" title="1、安装 serialVersionUID 插件："></a>1、安装 serialVersionUID 插件：</h3><p>若你的IDEA已安装，则跳过此步骤；</p><p>若未安装，参考 <a href="http://blog.csdn.net/qq_21033663/article/details/78477309">IDEA插件安装</a>，搜索插件时使用关键词“serialVersionUID ”</p><h3 id="2、设置你的IDEA为检查序列化ID"><a href="#2、设置你的IDEA为检查序列化ID" class="headerlink" title="2、设置你的IDEA为检查序列化ID"></a>2、设置你的IDEA为检查序列化ID</h3><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/idea_serializable_UID.png"></p><h3 id="3、重启IDEA"><a href="#3、重启IDEA" class="headerlink" title="3、重启IDEA"></a>3、重启IDEA</h3><p>有的版本可以不重启,比如小编使用的<br>IntelliJ IDEA 2019.2.3 (Ultimate Edition)</p><p>就不需要重新启动,设置好后点击确定即可</p><p>这个可以根据实际情况而定</p><h3 id="4、在需要自动生成序列化ID的类中使用快捷键-Alt-Insert"><a href="#4、在需要自动生成序列化ID的类中使用快捷键-Alt-Insert" class="headerlink" title="4、在需要自动生成序列化ID的类中使用快捷键:Alt+Insert"></a>4、在需要自动生成序列化ID的类中使用快捷键:Alt+Insert</h3><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/idea_generate.png"></p><h3 id="本文参考"><a href="#本文参考" class="headerlink" title="本文参考"></a>本文参考</h3><p><a href="https://1978413822.github.io/">岳阳-丁’s blog</a>的<a href="https://1978413822.github.io/2019/10/29/2019-10-29-idea%E4%B8%AD%E5%8A%A0%E5%BA%8F%E5%88%97%E5%8C%96/">IDEA加序列化</a></p><h3 id="相关推荐"><a href="#相关推荐" class="headerlink" title="相关推荐"></a>相关推荐</h3><p><a href="https://victorfengming.gitee.io/blog/git-idea/">在idea中使用git管理你的项目</a></p><p><a href="https://victorfengming.gitee.io/blog/jetbrains-idea-introduce/">关于宇宙最强Java编辑器:IntelliJ IDEA</a></p><p><a href="https://victorfengming.gitee.io/blog/jetbrains-idea-debug/">在IDEA中调试代码</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> idea </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记13-兄弟连在线考试系统</title>
      <link href="java/javase/note/note13/"/>
      <url>java/javase/note/note13/</url>
      
        <content type="html"><![CDATA[<h1 id="今天内容："><a href="#今天内容：" class="headerlink" title="今天内容："></a>今天内容：</h1><p>   1.兄弟连在线考试系统  </p><h3 id="具体实现代码"><a href="#具体实现代码" class="headerlink" title="具体实现代码"></a>具体实现代码</h3><p>去github看吧:<a href="https://github.com/victorfengming/xdl_exam_system">https://github.com/victorfengming/xdl_exam_system</a>  </p><p>感觉有用的可以给小编点个<code>star</code>  </p><h3 id="1-1-软件开发的流程"><a href="#1-1-软件开发的流程" class="headerlink" title="1.1 软件开发的流程"></a>1.1 软件开发的流程</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">   需求分析文档 &#x3D;&gt; 概要设计文档 &#x3D;&gt; 详细设计文档  &#x3D;&gt; 编码和测试  </span><br><span class="line">&#96;&#96;&#96;  </span><br><span class="line">  </span><br><span class="line">### 1.2 编写目的  </span><br><span class="line">   (1)复习JavaSE所学的所有内容。  </span><br><span class="line">   (2)锻炼基本的编程能力。  </span><br><span class="line">  </span><br><span class="line">### 1.3 功能分析  </span><br><span class="line">&#96;&#96;&#96;  </span><br><span class="line">   考试系统：  </span><br><span class="line">       (1)学员系统  </span><br><span class="line">          a.修改密码  </span><br><span class="line">          b.开始考试  </span><br><span class="line">          c.查询成绩  </span><br><span class="line">          d.导出成绩  </span><br><span class="line">          ...  </span><br><span class="line">          e.退出  </span><br><span class="line">       (2)管理员系统   </span><br><span class="line">          a.学员管理  </span><br><span class="line">            增加、删除、修改、查找、...  </span><br><span class="line">          b.试题管理  </span><br><span class="line">            增加、删除、修改、查找、...  </span><br><span class="line">&#96;&#96;&#96;  </span><br><span class="line">  </span><br><span class="line">### 1.4 项目的架构  </span><br><span class="line">&#96;&#96;&#96;angular2</span><br><span class="line"></span><br><span class="line">   项目采用C&#x2F;S架构进行设计，分为3层分别处理，具体流程：  </span><br><span class="line">       a.启动客户端让客户根据界面进行业务的选择并将相关信息发送给服务器；  </span><br><span class="line">       b.服务器通过访问数据库的方式进行业务处理并将处理结果发送给客户端；  </span><br><span class="line">       c.客户端将处理结果显示给客户；  </span><br></pre></td></tr></table></figure><h3 id="1-5-实现方式"><a href="#1-5-实现方式" class="headerlink" title="1.5 实现方式"></a>1.5 实现方式</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">(1)客户端与服务器之间采用基于tcp协议的网络编程进行通信；  </span><br><span class="line">(2)使用ObjectOutputStream和ObjectInputStream类进行对象的传输；  </span><br><span class="line">(3)使用字符串的类型作为客户端与服务器业务功能的标志；  </span><br><span class="line">   如：  </span><br><span class="line">     当客户端发送给服务器的类型是&quot;userCheck&quot;时，则服务器按照学员登录处理  </span><br><span class="line">     当客户端发送给服务器的类型是&quot;managerCheck&quot;时，则服务器按照管理员处理  </span><br><span class="line">     当服务器给客户端发送成功的结果时，服务器可以将类型改为&quot;success&quot;再回发  </span><br><span class="line">     当服务器给客户端发送失败的结果时，服务器可以将类型改为&quot;fail&quot;再回发  </span><br></pre></td></tr></table></figure><h3 id="1-6-学员管理功能的实现方式"><a href="#1-6-学员管理功能的实现方式" class="headerlink" title="1.6 学员管理功能的实现方式"></a>1.6 学员管理功能的实现方式</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">   学员管理界面  &#x3D;&gt; 选择增加学员 &#x3D;&gt; 从键盘输入学员用户名和密码信息并发送服务器  </span><br><span class="line">&#x3D;&gt; 服务器接收到学员信息后添加到集合中 &#x3D;&gt; 将增加的结果回发给客户端  &#x3D;&gt; 客户端接收到回发的处理结果后给出提示即可。  </span><br><span class="line">  </span><br><span class="line">   由于Java语言中不便于直接对文件内容增删改查，因此实现管理功能的思路如下：  </span><br><span class="line">        a.当项目启动时，将文件中所有学员信息读取到List集合中；  </span><br><span class="line">        b.在集合中对学员信息进行增删改查操作；  </span><br><span class="line">        c.当项目退出时，将集合中所有学员信息写入到文件中；  </span><br><span class="line">  </span><br></pre></td></tr></table></figure><h3 id="1-7-试题管理功能的实现方式"><a href="#1-7-试题管理功能的实现方式" class="headerlink" title="1.7 试题管理功能的实现方式"></a>1.7 试题管理功能的实现方式</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">这个与学员管理类似,只不过需要创建一个list集合来存储试题对象</span><br><span class="line">每个试题对象中绑定对应的属性:</span><br><span class="line">例如,试题的标题,试题的选项数组,试题的答案...</span><br><span class="line">然后对这个存储试题对象的list进行相应的增删改查操作,最后将整个list写入文件即可</span><br></pre></td></tr></table></figure><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">这个项目主要用到的是IO流的操作,其中包括Socket在客户端和服务端收发的数据,还有对于服务端数据的保存和读取</span><br><span class="line"></span><br><span class="line">所以,想要写好这个项目,需要有一定的javaSE的基础,以及面向对象思想的应用</span><br><span class="line"></span><br><span class="line">其中在进行系统层级的进入的时候,多次用到了&#96;try...catch&#96;,&#96;while(true)&#96;,&#96;if else if&#96;等结构,所以</span><br><span class="line"></span><br><span class="line">对于基础的流程控制也要掌握扎实</span><br><span class="line"></span><br><span class="line">这个项目虽然说采用的是C&#x2F;S架构,但是在客户端仅仅是在系统的控制台进行与用户的交互,这个地方需要加入图形化的界面才更加的万完整,才能给用户更加良好的交互体验.</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java学习路线导航,带你走向CTO</title>
      <link href="java/javaold/java-route/"/>
      <url>java/javaold/java-route/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为博主原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接和本声明。</p><p>本文链接：<a href="https://blog.csdn.net/qq_42453117/article/details/100655512">https://blog.csdn.net/qq_42453117/article/details/100655512</a></p><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>最近也有很多人来向我”请教”，他们大都是一些刚入门的新手，还不了解这个行业，也不知道从何学起，开始的时候非常迷茫，实在是每天回复很多人也很麻烦，所以在这里统一作个回复吧。</p><h3 id="Java学习路线"><a href="#Java学习路线" class="headerlink" title="Java学习路线"></a>Java学习路线</h3><p>当然，这里我只是说Java学习路线，因为自己就是学Java的，对Java理当很熟悉，对于其它方面，我也不是很了解。</p><h3 id="基础阶段"><a href="#基础阶段" class="headerlink" title="基础阶段"></a>基础阶段</h3><p>首先是基础阶段，在基础阶段，我们必须掌握Java基础，Mysql数据库，Oracle数据库，JDBC，Linux基础，Java8新特性，数据结构和算法，设计模式。<br>对于基础阶段，我们所要掌握的就是基础，虽然是基础，但学起来也够呛。因为是初学者，所以基础阶段会有一点难度，但只要肯坚持，这些也没什么难的。对于Linux、数据结构、算法和设计模式我们掌握一些基础就行了，也没必要学得非常透彻。</p><h3 id="Web基础"><a href="#Web基础" class="headerlink" title="Web基础"></a>Web基础</h3><p>基础阶段过后，我们还必须要掌握一些Web方面的知识，Html，JavaScript，JQuery和AJax，同样的，对于这些知识，我们只需掌握基础，而不需要深究，否则，你将耗费大量的时间。</p><h3 id="JavaWeb"><a href="#JavaWeb" class="headerlink" title="JavaWeb"></a>JavaWeb</h3><p>Web阶段过后，当然就是JavaWeb了，对于JavaWeb，我们需要掌握的知识有：Servlet，JSP，MVC设计模式，Cookie，Session，JavBean组件技术，EL表达式，JSTL表达式，过滤器Filter，监听器Listener，文件的上传下载，国际化。</p><h3 id="JavaEE"><a href="#JavaEE" class="headerlink" title="JavaEE"></a>JavaEE</h3><p>最后是JavaEE阶段，当你学到这个阶段，你对Java的程序开发已经了如指掌。然而，自己开发的过程是艰难而复杂的，所以JavaEE阶段我们需要去学习一些非常优秀的框架，来帮助我们进行程序开发。<br>对于框架，我们需要学习Struts2，Hibernate，Spring，SpringMVC，JPA，SpringData，MyBatis，Spring Boot，Spring Cloud，Dubbo。要学习的框架其实非常多，有些框架也十分有难度，我们在学习阶段只要能够熟练使用它们即可，有能力的话可以研究一下源码，看看框架的底层实现。当然，除了框架，我们还需要学习Maven，Git，Github，ActiveMQ，Jenkins等。<br>在JavaEE阶段学习的东西是最多的，但如果你经历了JavaEE阶段的学习，你的编程水平将会有质的飞跃。</p><h3 id="其它"><a href="#其它" class="headerlink" title="其它"></a>其它</h3><p>这里是我在写了这篇文章几天后才加上的，有人向我反映，说数据结构和算法不学好就只能当个码农，说我在文章中指出”只需学习数据结构和算法的基础即可”是误导别人。确实，这句话是没说错，我在之前的文章中也强调过数据结构和算法的重要性，它们是程序的灵魂。然而，数据结构和算法是具有一定难度的，对于新手可能非常地不友好，新手要想彻底掌握它们是很困难的，所以我只是说在基础阶段掌握基础即可，而不需要去深究。而随着学习的深入，你的知识体系将会越来越庞大，这个时候，对于数据结构和算法可不能仅仅停留在表面了，我们应该去更加深入地研究这些东西。<br>在这里也感谢大家给我提出的意见，只要大家说的在理，说的是对的，我都会去及时改正。金无足赤，人无完人，在写文章的过程中，难免会有一些不太严谨的地方，这里也欢迎大家批评指正。</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记12-函数式接口</title>
      <link href="java/javase/note/note12/"/>
      <url>java/javase/note/note12/</url>
      
        <content type="html"><![CDATA[<h3 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h3><ul><li>自定义函数式接口</li><li>函数式编程</li><li>常用函数式接口</li></ul><h3 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h3><ul><li>能够使用@FunctionalInterface注解</li><li>能够自定义无参无返回值函数式接口</li><li>能够自定义有参有返回值函数式接口</li><li>能够理解Lambda延迟执行的特点</li><li>能够使用Lambda作为方法的参数</li><li>能够使用Lambda作为方法的返回值</li><li>能够使用Supplier函数式接口</li><li>能够使用Consumer函数式接口</li><li>能够使用Function函数式接口</li><li>能够使用Predicate函数式接口</li></ul><h1 id="第一章-函数式接口"><a href="#第一章-函数式接口" class="headerlink" title="第一章 函数式接口"></a>第一章 函数式接口</h1><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>函数式接口在java中指的是:有且只有一个抽象方法的接口</p><p>函数式接口,即适用于函数式编程场景的接口.而java中共的函数式编程体现就是Lambda,所以函数式接口就是可以适用于lambda使用的接口.只有确保接口中有且只有一个宠幸方法,java中的lambda才能顺利地进行推导.</p><p>备注:语法糖是指使用更加方便,但是原理不变的代码语法,例如在遍历集合时使用for-each语法,其实底层的实现原理仍然是迭代器,这便是语法糖.从应用应用层面来京,java中的lambda可以被当做是匿名内部类了的语法糖,但是二者原理上是不同的.</p><h3 id="格式"><a href="#格式" class="headerlink" title="格式"></a>格式</h3><p>只要确保接口中有且仅有一个抽象方法即可:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">修饰符 Interface 接口名称&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">abstract</span> 返回值类型 方法名称(可选参数信息);</span><br><span class="line">    <span class="comment">// 其他非抽象方法内容</span></span><br><span class="line">&#125;</span><br><span class="line">```    </span><br><span class="line">由于接口当中抽象方法的<span class="keyword">public</span> <span class="keyword">abstract</span> 是可以省略的,所以定义一函数式接口很简单:</span><br><span class="line">```java</span><br><span class="line"><span class="keyword">public</span> Interface MyFunctionalInterface&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">myMethod</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="FunctionalInterface注解"><a href="#FunctionalInterface注解" class="headerlink" title="@FunctionalInterface注解"></a>@FunctionalInterface注解</h3><p>与<code>@Override</code>注解的作用类似,Java 8 中专门为函数式接口引入了一个新的注解:<code>@FunctionInterface</code>.该注解可用于一个接口的定义上:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@FunctionalInterface</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">MyFunctionalInterface</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">myMethod</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>一旦使用该注解来定义接口,编译期将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错.需要<strong>注意</strong>的是,即使不使用该注解,主要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一个B样,只不过<code>@FunctionalInterface</code>用起来规范一点,说白了逼格高那么一丢丢</p><h3 id="自定义函数式接口"><a href="#自定义函数式接口" class="headerlink" title="自定义函数式接口"></a>自定义函数式接口</h3><p>对于刚刚定义好的<code>MyFunctionalInterface</code>函数式接口,典型使用场景就是作为方法的参数:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo09FunctionalInterface</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 使用自定义的函数式接口作为方法参数</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">doSomething</span><span class="params">(MyFunctionalInterface inter)</span> </span>&#123;</span><br><span class="line">        inter.myMethod(); <span class="comment">// 调用自定义的函数式接口方法 </span></span><br><span class="line">    &#125;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span> <span class="params">(String[]args)</span></span>&#123;</span><br><span class="line">            <span class="comment">// 调用使用函数式接口的方法</span></span><br><span class="line">            doSomething(() ‐ &gt; System.out.println(<span class="string">&quot;Lambda执行啦!&quot;</span>));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="函数式编程"><a href="#函数式编程" class="headerlink" title="函数式编程"></a>函数式编程</h1><p>在兼顾面向对象特性的基础上,Java语言通过Lambda表达式与方法引用等,为开发者打开了函数式编程的大门</p><p>下面我们做一个初探</p><h3 id="Lambda的延迟执行"><a href="#Lambda的延迟执行" class="headerlink" title="Lambda的延迟执行"></a>Lambda的延迟执行</h3><p>有些场景的代码执行后，结果不一定会被使用，从而造成性能浪费。而Lambda表达式是延迟执行的，这正好可以 作为解决方案，提升性能。</p><h3 id="性能浪费的日志案例"><a href="#性能浪费的日志案例" class="headerlink" title="性能浪费的日志案例"></a>性能浪费的日志案例</h3><p>注:日志可以帮助我们快速的定位问题，记录程序运行过程中的情况，以便项目的监控和优化。 一种典型的场景就是对参数进行有条件使用，例如对日志消息进行拼接后，在满足条件的情况下进行打印输出:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01Logger</span> </span>&#123;</span><br><span class="line">       <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">log</span><span class="params">(<span class="keyword">int</span> level, String msg)</span> </span>&#123;</span><br><span class="line">           <span class="keyword">if</span> (level == <span class="number">1</span>) &#123;</span><br><span class="line">               System.out.println(msg);</span><br><span class="line">&#125; &#125;</span><br><span class="line">       <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">           String msgA = <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line">           String msgB = <span class="string">&quot;World&quot;</span>;</span><br><span class="line">           String msgC = <span class="string">&quot;Java&quot;</span>;</span><br><span class="line">           log(<span class="number">1</span>, msgA + msgB + msgC);</span><br><span class="line">       &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这段代码存在问题:无论级别是否满足要求，作为 <code>log</code> 方法的第二个参数，三个字符串一定会首先被拼接并传入方<br>法内，然后才会进行级别判断。如果级别不符合要求，那么字符串的拼接操作就白做了，存在性能浪费。</p><p>备注:SLF4J是应用非常广泛的日志框架，它在记录日志时为了解决这种性能浪费的问题，并不推荐首先进行 字符串的拼接，而是将字符串的若干部分作为可变参数传入方法中，仅在日志级别满足要求的情况下才会进 行字符串拼接。例如: LOGGER.debug(“变量{}的取值为{}。”, “os”, “macOS”) ，其中的大括号 {} 为占位 符。如果满足日志级别要求，则会将“os”和“macOS”两个字符串依次拼接到大括号的位置;否则不会进行字 符串拼接。这也是一种可行解决方案，但Lambda可以做到更好。</p><h3 id="体验lambda的更加优化写法"><a href="#体验lambda的更加优化写法" class="headerlink" title="体验lambda的更加优化写法"></a>体验lambda的更加优化写法</h3><p>使用Lambda必然需要一个函数式接口:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@FunctionalInterface</span></span><br><span class="line">   <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">MessageBuilder</span> </span>&#123;</span><br><span class="line">       <span class="function">String <span class="title">buildMessage</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后对 log 方法进行改造:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo02LoggerLambda</span> </span>&#123;</span><br><span class="line">       <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">log</span><span class="params">(<span class="keyword">int</span> level, MessageBuilder builder)</span> </span>&#123;</span><br><span class="line">           <span class="keyword">if</span> (level == <span class="number">1</span>) &#123;</span><br><span class="line">               System.out.println(builder.buildMessage());</span><br><span class="line">           &#125; </span><br><span class="line">       &#125;</span><br><span class="line">       <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">           String msgA = <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line">           String msgB = <span class="string">&quot;World&quot;</span>;</span><br><span class="line">           String msgC = <span class="string">&quot;Java&quot;</span>;</span><br><span class="line">           log(<span class="number">1</span>, () ‐&gt; msgA + msgB + msgC );</span><br><span class="line">       &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样一来，只有当级别满足要求的时候，才会进行三个字符串的拼接;否则三个字符串将不会进行拼接。</p><h3 id="证明lambda的延迟"><a href="#证明lambda的延迟" class="headerlink" title="证明lambda的延迟"></a>证明lambda的延迟</h3><p>下面的代码可以通过结果进行验证:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo03LoggerDelay</span> </span>&#123;</span><br><span class="line">       <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">log</span><span class="params">(<span class="keyword">int</span> level, MessageBuilder builder)</span> </span>&#123;</span><br><span class="line">           <span class="keyword">if</span> (level == <span class="number">1</span>) &#123;</span><br><span class="line">               System.out.println(builder.buildMessage());</span><br><span class="line">           &#125; </span><br><span class="line">       &#125;</span><br><span class="line">       <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">           String msgA = <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line">           String msgB = <span class="string">&quot;World&quot;</span>;</span><br><span class="line">           String msgC = <span class="string">&quot;Java&quot;</span>;</span><br><span class="line">           log(<span class="number">2</span>, () ‐&gt; &#123;</span><br><span class="line">               System.out.println(<span class="string">&quot;Lambda执行!&quot;</span>);</span><br><span class="line">               <span class="keyword">return</span> msgA + msgB + msgC;</span><br><span class="line">           &#125;); </span><br><span class="line">       &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>从结果中可以看出，在不符合级别要求的情况下，Lambda将不会执行。从而达到节省性能的效果。 </p><p>扩展:实际上使用内部类也可以达到同样的效果，只是将代码操作延迟到了另外一个对象当中通过调用方法来完成。而是否调用其所在方法是在条件判断之后才执行的。</p><h3 id="使用Lambda作为参数和返回值"><a href="#使用Lambda作为参数和返回值" class="headerlink" title="使用Lambda作为参数和返回值"></a>使用Lambda作为参数和返回值</h3><p>如果抛开实现原理不说，Java中的<code>Lambda</code>表达式可以被当作是匿名内部类的替代品。如果方法的参数是一个函数 式接口类型，那么就可以使用Lambda表达式进行替代。使用Lambda表达式作为方法参数，其实就是使用函数式 接口作为方法参数。<br>例如 <code>java.lang.Runnable </code>接口就是一个函数式接口，假设有一个 <code>startThread</code> 方法使用该接口作为参数，那么就 可以使用<code>Lambda</code>进行传参。这种情况其实和 <code>Thread</code> 类的构造方法参数为 <code>Runnable</code> 没有本质区别。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo04Runnable</span> </span>&#123;</span><br><span class="line">       <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">startThread</span><span class="params">(Runnable task)</span> </span>&#123;</span><br><span class="line">           <span class="keyword">new</span> Thread(task).start();</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">           startThread(() ‐&gt; System.out.println(<span class="string">&quot;线程任务执行!&quot;</span>));</span><br><span class="line">       &#125;       </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>类似地，如果一个方法的返回值类型是一个函数式接口，那么就可以直接返回一个Lambda表达式。当需要通过一个方法来获取一个 <code>java.util.Comparator</code> 接口类型的对象作为排序器时,就可以调该方法获取。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"><span class="keyword">import</span> java.util.Comparator;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo06Comparator</span> </span>&#123;</span><br><span class="line">       <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> Comparator&lt;String&gt; <span class="title">newComparator</span><span class="params">()</span> </span>&#123;</span><br><span class="line">           <span class="keyword">return</span> (a, b) ‐&gt; b.length() ‐ a.length();</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">           String[] array = &#123; <span class="string">&quot;abc&quot;</span>, <span class="string">&quot;ab&quot;</span>, <span class="string">&quot;abcd&quot;</span> &#125;;</span><br><span class="line">           System.out.println(Arrays.toString(array));</span><br><span class="line">           Arrays.sort(array, newComparator());</span><br><span class="line">           System.out.println(Arrays.toString(array));</span><br><span class="line">        &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中直接return一个Lambda表达式即可</p><h1 id="常用函数式接口"><a href="#常用函数式接口" class="headerlink" title="常用函数式接口"></a>常用函数式接口</h1><p>JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景，它们主要在 <code>java.util.function</code> 包中被提供。 下面是最简单的几个接口及使用示例。</p><h3 id="supplier接口"><a href="#supplier接口" class="headerlink" title="supplier接口"></a>supplier接口</h3><p><code>java.util.function.Supplier&lt;T&gt; </code>接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对 象数据。由于这是一个函数式接口，这也就意味着对应的Lambda表达式需要<strong>对外提供</strong>一个符合泛型类型的对象 数据。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.function.Supplier;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo08Supplier</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> String <span class="title">getString</span><span class="params">(Supplier&lt;String&gt; function)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> function.get();</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       String msgA = <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line">       String msgB = <span class="string">&quot;World&quot;</span>;</span><br><span class="line">       System.out.println(getString(() ‐&gt; msgA + msgB));</span><br><span class="line">   &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="练习-求数组元素的最大值"><a href="#练习-求数组元素的最大值" class="headerlink" title="练习:求数组元素的最大值"></a>练习:求数组元素的最大值</h3><p>题目:</p><p>使用 Supplier 接口作为方法参数类型，通过Lambda表达式求出int数组中的最大值。提示:接口的泛型请使用 java.lang.Integer 类。<br>解答:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo02Test</span> </span>&#123; </span><br><span class="line">    <span class="comment">//定一个方法,方法的参数传递Supplier,泛型使用Integer </span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getMax</span><span class="params">(Supplier&lt;Integer&gt; sup)</span></span>&#123;</span><br><span class="line">       <span class="keyword">return</span> sup.get();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">int</span> arr[] = &#123;<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">52</span>,<span class="number">333</span>,<span class="number">23</span>&#125;;</span><br><span class="line">            <span class="comment">//调用getMax方法,参数传递Lambda </span></span><br><span class="line">       <span class="keyword">int</span> maxNum = getMax(()‐&gt;&#123;</span><br><span class="line">            <span class="comment">//计算数组的最大值 </span></span><br><span class="line">            <span class="keyword">int</span> max = arr[<span class="number">0</span>]; <span class="keyword">for</span>(<span class="keyword">int</span> i : arr)&#123;</span><br><span class="line">                <span class="keyword">if</span>(i&gt;max)&#123;</span><br><span class="line">                   max = i;</span><br><span class="line">                &#125; </span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> max;</span><br><span class="line">       &#125;);</span><br><span class="line">       System.out.println(maxNum);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Consumer接口"><a href="#Consumer接口" class="headerlink" title="Consumer接口"></a>Consumer接口</h3><p> <code>java.util.function.Consumer&lt;T&gt; </code>接口则正好与Supplier接口相反，它不是生产一个数据，而是消费一个数据， 其数据类型由泛型决定。</p><h3 id="抽象方法-accept"><a href="#抽象方法-accept" class="headerlink" title="抽象方法:accept"></a>抽象方法:accept</h3><p><code>Consumer</code> 接口中包含抽象方法 <code>void accept(T t)</code> ，意为消费一个指定泛型的数据。基本使用如:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.function.Consumer;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo09Consumer</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">consumeString</span><span class="params">(Consumer&lt;String&gt; function)</span> </span>&#123;</span><br><span class="line">       function.accept(<span class="string">&quot;Hello&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       consumeString(s ‐&gt; System.out.println(s));</span><br><span class="line">   &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当然，更好的写法是使用方法引用。</p><h3 id="默认方法-andThen"><a href="#默认方法-andThen" class="headerlink" title="默认方法:andThen"></a>默认方法:andThen</h3><p>如果一个方法的参数和返回值全都是 Consumer 类型，那么就可以实现效果:消费数据的时候，首先做一个操作， 然后再做一个操作，实现组合。而这个方法就是 Consumer 接口中的default方法 andThen 。下面是JDK的源代码:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">default</span> Consumer&lt;T&gt; <span class="title">andThen</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> T&gt; after)</span> </span>&#123;</span><br><span class="line">       Objects.requireNonNull(after);</span><br><span class="line">       <span class="keyword">return</span> (T t) ‐&gt; &#123; accept(t); after.accept(t); &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>备注: java.util.Objects 的 requireNonNull 静态方法将会在参数为null时主动抛出 NullPointerException 异常。这省去了重复编写if语句和抛出空指针异常的麻烦。<br>要想实现组合，需要两个或多个Lambda表达式即可，而 andThen 的语义正是“一步接一步”操作。例如两个步骤组 合的情况:    </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.function.Consumer;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo10ConsumerAndThen</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">consumeString</span><span class="params">(Consumer&lt;String&gt; one, Consumer&lt;String&gt; two)</span> </span>&#123;</span><br><span class="line">       one.andThen(two).accept(<span class="string">&quot;Hello&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       consumeString(</span><br><span class="line">            s ‐&gt; System.out.println(s.toUpperCase()),</span><br><span class="line">            s ‐&gt; System.out.println(s.toLowerCase()));</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果将会首先打印完全大写的HELLO，然后打印完全小写的hello。当然，通过链式写法可以实现更多步骤的 组合。</p><h3 id="练习-格式化打印信息"><a href="#练习-格式化打印信息" class="headerlink" title="练习:格式化打印信息"></a>练习:格式化打印信息</h3><p>题目<br>下面的字符串数组当中存有多条信息，请按照格式“ <code>姓名:XX。性别:XX。</code> ”的格式将信息打印出来。要求将打印姓 名的动作作为第一个 <code>Consumer </code>接口的Lambda实例，将打印性别的动作作为第二个 <code>Consumer </code>接口的Lambda实 例，将两个 <code>Consumer </code>接口按照顺序“拼接”到一起。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">    String[] array = &#123;<span class="string">&quot;迪丽热巴,女&quot;</span>,<span class="string">&quot;古力娜扎,女&quot;</span>,<span class="string">&quot;马尔扎哈,男&quot;</span>&#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>解答</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.function.Consumer;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DemoConsumer</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String[] array = &#123; <span class="string">&quot;迪丽热巴,女&quot;</span>, <span class="string">&quot;古力娜扎,女&quot;</span>, <span class="string">&quot;马尔扎哈,男&quot;</span> &#125;;</span><br><span class="line">        printInfo(s ‐&gt; System.out.print(<span class="string">&quot;姓名:&quot;</span> + s.split(<span class="string">&quot;,&quot;</span>)[<span class="number">0</span>]),</span><br><span class="line">        s ‐&gt; System.out.println(<span class="string">&quot;。性别:&quot;</span> + s.split(<span class="string">&quot;,&quot;</span>)[<span class="number">1</span>] + <span class="string">&quot;。&quot;</span>),</span><br><span class="line">        array);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">printInfo</span><span class="params">(Consumer&lt;String&gt; one, Consumer&lt;String&gt; two, String[] array)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">for</span> (String info : array) &#123;</span><br><span class="line">    one.andThen(two).accept(info); <span class="comment">// 姓名:迪丽热巴。性别:女。 </span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Predicate接口"><a href="#Predicate接口" class="headerlink" title="Predicate接口"></a>Predicate接口</h3><p>有时候我们需要对某种类型的数据进行判断，从而得到一个boolean值结果。这时可以使用<br><code>java.util.function.Predicate&lt;T&gt;</code> 接口。</p><h3 id="抽象方法-test"><a href="#抽象方法-test" class="headerlink" title="抽象方法:test"></a>抽象方法:test</h3><p><code>Predicate</code> 接口中包含一个抽象方法: <code>boolean test(T t)</code> 。用于条件判断的场景:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.function.Predicate</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo15PredicateTest</span> </span>&#123;</span><br><span class="line">       <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">method</span><span class="params">(Predicate&lt;String&gt; predicate)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">boolean</span> veryLong = predicate.test(<span class="string">&quot;HelloWorld&quot;</span>);</span><br><span class="line">            System.out.println(<span class="string">&quot;字符串很长吗:&quot;</span> + veryLong); </span><br><span class="line">       &#125;</span><br><span class="line">       <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">           method(s ‐&gt; s.length() &gt; <span class="number">5</span>);</span><br><span class="line">       &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>条件判断的标准是传入的Lambda表达式逻辑，只要字符串长度大于5则认为很长。</p><h3 id="默认方法-and"><a href="#默认方法-and" class="headerlink" title="默认方法:and"></a>默认方法:and</h3><p>既然是条件判断，就会存在与、或、非三种常见的逻辑关系。其中将两个 Predicate 条件使用“与”逻辑连接起来实 现“<strong>并且</strong>”的效果时，可以使用default方法 and 。其JDK源码为:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">default</span> Predicate&lt;T&gt; <span class="title">and</span><span class="params">(Predicate&lt;? <span class="keyword">super</span> T&gt; other)</span> </span>&#123;</span><br><span class="line">       Objects.requireNonNull(other);</span><br><span class="line">       <span class="keyword">return</span> (t) ‐&gt; test(t) &amp;&amp; other.test(t);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如果要判断一个字符串既要包含大写“H”，又要包含大写“W”，那么:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.function.Predicate;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo16PredicateAnd</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">method</span><span class="params">(Predicate&lt;String&gt; one, Predicate&lt;String&gt; two)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">boolean</span> isValid = one.and(two).test(<span class="string">&quot;Helloworld&quot;</span>);</span><br><span class="line">       System.out.println(<span class="string">&quot;字符串符合要求吗:&quot;</span> + isValid); </span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       method(s ‐&gt; s.contains(<span class="string">&quot;H&quot;</span>), s ‐&gt; s.contains(<span class="string">&quot;W&quot;</span>));</span><br><span class="line">   &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="默认方法-or"><a href="#默认方法-or" class="headerlink" title="默认方法:or"></a>默认方法:or</h3><p>与 <code>and</code> 的“与”类似，默认方法 <code>or</code> 实现逻辑关系中的“或”。JDK源码为:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">default</span> Predicate&lt;T&gt; <span class="title">or</span><span class="params">(Predicate&lt;? <span class="keyword">super</span> T&gt; other)</span> </span>&#123;</span><br><span class="line">       Objects.requireNonNull(other);</span><br><span class="line">       <span class="keyword">return</span> (t) ‐&gt; test(t) || other.test(t);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如果希望实现逻辑“字符串包含大写H或者包含大写W”，那么代码只需要将“and”修改为“or”名称即可，其他都不变:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.function.Predicate;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo16PredicateAnd</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">method</span><span class="params">(Predicate&lt;String&gt; one, Predicate&lt;String&gt; two)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">boolean</span> isValid = one.or(two).test(<span class="string">&quot;Helloworld&quot;</span>);</span><br><span class="line">       System.out.println(<span class="string">&quot;字符串符合要求吗:&quot;</span> + isValid); </span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       method(s ‐&gt; s.contains(<span class="string">&quot;H&quot;</span>), s ‐&gt; s.contains(<span class="string">&quot;W&quot;</span>));</span><br><span class="line">   &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="默认方法-negate"><a href="#默认方法-negate" class="headerlink" title="默认方法:negate"></a>默认方法:negate</h3><p>“与”、“或”已经了解了，剩下的“非”(取反)也会简单。默认方法 negate 的JDK源代码为</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">default</span> Predicate&lt;T&gt; <span class="title">negate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> (t) ‐&gt; !test(t);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>从实现中很容易看出，它是执行了test方法之后，对结果boolean值进行“!”取反而已。一定要在 <code>test</code> 方法调用之前<br>调用 <code>negate</code> 方法，正如 <code>and</code> 和 <code>or</code> 方法一样:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.function.Predicate;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo17PredicateNegate</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">method</span><span class="params">(Predicate&lt;String&gt; predicate)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">boolean</span> veryLong = predicate.negate().test(<span class="string">&quot;HelloWorld&quot;</span>);</span><br><span class="line">       System.out.println(<span class="string">&quot;字符串很长吗:&quot;</span> + veryLong); </span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       method(s ‐&gt; s.length() &lt; <span class="number">5</span>);</span><br><span class="line">&#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="练习-集合信息筛选-题目"><a href="#练习-集合信息筛选-题目" class="headerlink" title="练习:集合信息筛选 题目"></a>练习:集合信息筛选 题目</h3><p>数组当中有多条“姓名+性别”的信息如下，请通过 Predicate 接口的拼装将符合要求的字符串筛选到集合 ArrayList 中，需要同时满足两个条件:</p><ul><li><ol><li>必须为女生; </li></ol></li><li><ol start="2"><li>姓名为4个字。</li></ol></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DemoPredicate</span> </span>&#123;</span><br><span class="line">       <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">            String[] array = &#123; <span class="string">&quot;迪丽热巴,女&quot;</span>, <span class="string">&quot;古力娜扎,女&quot;</span>, <span class="string">&quot;马尔扎哈,男&quot;</span>, <span class="string">&quot;赵丽颖,女&quot;</span> &#125;; </span><br><span class="line">       &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>解答</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.function.Predicate;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DemoPredicate</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String[] array = &#123; <span class="string">&quot;迪丽热巴,女&quot;</span>, <span class="string">&quot;古力娜扎,女&quot;</span>, <span class="string">&quot;马尔扎哈,男&quot;</span>, <span class="string">&quot;赵丽颖,女&quot;</span> &#125;; List&lt;String&gt; list = filter(array,</span><br><span class="line">        s ‐&gt; <span class="string">&quot;女&quot;</span>.equals(s.split(<span class="string">&quot;,&quot;</span>)[<span class="number">1</span>]),</span><br><span class="line">        s ‐&gt; s.split(<span class="string">&quot;,&quot;</span>)[<span class="number">0</span>].length() == <span class="number">4</span>);</span><br><span class="line">        System.out.println(list);</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> List&lt;String&gt; <span class="title">filter</span><span class="params">(String[] array, Predicate&lt;String&gt; one,</span></span></span><br><span class="line"><span class="function"><span class="params">                                      Predicate&lt;String&gt; two)</span> </span>&#123;</span><br><span class="line">       List&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">       <span class="keyword">for</span> (String info : array) &#123;</span><br><span class="line">           <span class="keyword">if</span> (one.and(two).test(info)) &#123;</span><br><span class="line">               list.add(info);</span><br><span class="line">           &#125; </span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> list;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中网络编程</title>
      <link href="java/javaold/java-web/"/>
      <url>java/javaold/java-web/</url>
      
        <content type="html"><![CDATA[<h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li> 软件架构CS／BS</li><li> 网络通信三要素</li><li> TCP通信</li><li> Socket套接字</li><li> ServerSocket</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><ul><li><input disabled="" type="checkbox"> 能够辨别UDP和TCP协议特点</li><li><input disabled="" type="checkbox"> 能够说出TCP协议下两个常用类名称</li><li><input disabled="" type="checkbox"> 能够编写TCP协议下字符串数据传输程序</li><li><input disabled="" type="checkbox"> 能够理解TCP协议下文件上传案例</li><li><input disabled="" type="checkbox"> 能够理解TCP协议下案例2</li></ul><h1 id="第一章-网络编程入门"><a href="#第一章-网络编程入门" class="headerlink" title="第一章 网络编程入门"></a>第一章 网络编程入门</h1><h2 id="1-1软件结构"><a href="#1-1软件结构" class="headerlink" title="1.1软件结构"></a>1.1软件结构</h2><ul><li><strong>C/S结构</strong> ：全称为Client/Server结构，是指客户端和服务器结构。常见程序有ＱＱ、迅雷等软件。</li></ul><p><img src= "/img/loading.gif" data-lazy-src="img/1_cs.jpg"></p><p><strong>B/S结构</strong> ：全称为Browser/Server结构，是指浏览器和服务器结构。常见浏览器有谷歌、火狐等。</p><p><img src= "/img/loading.gif" data-lazy-src="img/2_bs.jpg"></p><p>两种架构各有优势，但是无论哪种架构，都离不开网络的支持。<strong>网络编程</strong>，就是在一定的协议下，实现两台计算机的通信的程序。</p><h2 id="1-2-网络通信协议"><a href="#1-2-网络通信协议" class="headerlink" title="1.2 网络通信协议"></a>1.2 网络通信协议</h2><ul><li><strong>网络通信协议：</strong>通过计算机网络可以使多台计算机实现连接，位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则，这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中，这些连接和通信的规则被称为网络通信协议，它对数据的传输格式、传输速率、传输步骤等做了统一规定，通信双方必须同时遵守才能完成数据交换。</li></ul><ul><li><strong>TCP/IP协议：</strong> 传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol)，是Internet最基本、最广泛的协议。它定义了计算机如何连入因特网，以及数据如何在它们之间传输的标准。它的内部包含一系列的用于处理数据通信的协议，并采用了4层的分层模型，每一层都呼叫它的下一层所提供的协议来完成自己的需求。</li></ul><p><img src= "/img/loading.gif" data-lazy-src="img/3_tcp_ip.jpg"></p><p>上图中，TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层，每层分别负责不同的通信功能。<br>链路层：链路层是用于定义物理传输通道，通常是对某些网络连接设备的驱动协议，例如针对光纤、网线提供的驱动。<br>网络层：网络层是整个TCP/IP协议的核心，它主要用于将传输的数据进行分组，将分组数据发送到目标计算机或者网络。<br>运输层：主要使网络程序进行通信，在进行网络通信时，可以采用TCP协议，也可以采用UDP协议。<br>应用层：主要负责应用程序的协议，例如HTTP协议、FTP协议等。</p><h2 id="1-3-协议分类"><a href="#1-3-协议分类" class="headerlink" title="1.3 协议分类"></a>1.3 协议分类</h2><p>通信的协议还是比较复杂的，<code>java.net</code> 包中包含的类和接口，它们提供低层次的通信细节。我们可以直接使用这些类和接口，来专注于网络程序开发，而不用考虑通信的细节。</p><p><code>java.net</code> 包中提供了两种常见的网络协议的支持：</p><ul><li><p><strong>UDP</strong>：用户数据报协议(User Datagram Protocol)。UDP是无连接通信协议，即在数据传输时，数据的发送端和接收端不建立逻辑连接。简单来说，当一台计算机向另外一台计算机发送数据时，发送端不会确认接收端是否存在，就会发出数据，同样接收端在收到数据时，也不会向发送端反馈是否收到数据。</p><p>由于使用UDP协议消耗资源小，通信效率高，所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议，因为这种情况即使偶尔丢失一两个数据包，也不会对接收结果产生太大影响。</p><p>但是在使用UDP协议传送数据时，由于UDP的面向无连接性，不能保证数据的完整性，因此在传输重要数据时不建议使用UDP协议。UDP的交换过程如下图所示。</p></li></ul><p><img src= "/img/loading.gif" data-lazy-src="img%5CUDP%E9%80%9A%E4%BF%A1%E5%9B%BE%E8%A7%A3.bmp" alt="UDP通信图解"></p><p>特点:数据被限制在64kb以内，超出这个范围就不能发送了。</p><p>数据报(Datagram):网络传输的基本单位 </p><ul><li><p><strong>TCP</strong>：传输控制协议 (Transmission Control Protocol)。TCP协议是<strong>面向连接</strong>的通信协议，即传输数据之前，在发送端和接收端建立逻辑连接，然后再传输数据，它提供了两台计算机之间可靠无差错的数据传输。</p><p>在TCP连接中必须要明确客户端与服务器端，由客户端向服务端发出连接请求，每次连接的创建都需要经过“三次握手”。</p><ul><li>三次握手：TCP协议中，在发送数据的准备阶段，客户端与服务器之间的三次交互，以保证连接的可靠。<ul><li>第一次握手，客户端向服务器端发出连接请求，等待服务器确认。</li><li>第二次握手，服务器端向客户端回送一个响应，通知客户端收到了连接请求。</li><li>第三次握手，客户端再次向服务器端发送确认信息，确认连接。整个交互过程如下图所示。</li></ul></li></ul></li></ul><p><img src= "/img/loading.gif" data-lazy-src="img/4_tcp.jpg"></p><p>​    完成三次握手，连接建立后，客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性，TCP协议可以保证传输数据的安全，所以应用十分广泛，例如下载文件、浏览网页等。</p><h2 id="1-4-网络编程三要素"><a href="#1-4-网络编程三要素" class="headerlink" title="1.4 网络编程三要素"></a>1.4 网络编程三要素</h2><h3 id="协议"><a href="#协议" class="headerlink" title="协议"></a>协议</h3><ul><li><strong>协议：</strong>计算机网络通信必须遵守的规则，已经介绍过了，不再赘述。</li></ul><h3 id="IP地址"><a href="#IP地址" class="headerlink" title="IP地址"></a>IP地址</h3><ul><li><strong>IP地址：指互联网协议地址（Internet Protocol Address）</strong>，俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话，那么“IP地址”就相当于“电话号码”。</li></ul><p><strong>IP地址分类</strong></p><ul><li><p>IPv4：是一个32位的二进制数，通常被分为4个字节，表示成<code>a.b.c.d</code> 的形式，例如<code>192.168.65.100</code> 。其中a、b、c、d都是0~255之间的十进制整数，那么最多可以表示42亿个。</p></li><li><p>IPv6：由于互联网的蓬勃发展，IP地址的需求量愈来愈大，但是网络地址资源有限，使得IP的分配越发紧张。</p><p>为了扩大地址空间，拟通过IPv6重新定义地址空间，采用128位地址长度，每16个字节一组，分成8组十六进制数，表示成<code>ABCD:EF01:2345:6789:ABCD:EF01:2345:6789</code>，号称可以为全世界的每一粒沙子编上一个网址，这样就解决了网络地址资源数量不够的问题。</p></li></ul><p><strong>常用命令</strong></p><ul><li>查看本机IP地址，在控制台输入：</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ipconfig</span><br></pre></td></tr></table></figure><ul><li>检查网络是否连通，在控制台输入：</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ping 空格 IP地址</span><br><span class="line">ping <span class="number">220.181</span><span class="number">.57</span><span class="number">.216</span></span><br></pre></td></tr></table></figure><p><strong>特殊的IP地址</strong></p><ul><li>本机IP地址：<code>127.0.0.1</code>、<code>localhost</code> 。</li></ul><h3 id="端口号"><a href="#端口号" class="headerlink" title="端口号"></a>端口号</h3><p>网络的通信，本质上是两个进程（应用程序）的通信。每台计算机都有很多的进程，那么在网络通信时，如何区分这些进程呢？</p><p>如果说<strong>IP地址</strong>可以唯一标识网络中的设备，那么<strong>端口号</strong>就可以唯一标识设备中的进程（应用程序）了。</p><ul><li><strong>端口号：用两个字节表示的整数，它的取值范围是0~65535</strong>。其中，0~1023之间的端口号用于一些知名的网络服务和应用，普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用，会导致当前程序启动失败。</li></ul><p>利用<code>协议</code>+<code>IP地址</code>+<code>端口号</code> 三元组合，就可以标识网络中的进程了，那么进程间的通信就可以利用这个标识与其它进程进行交互。</p><h1 id="第二章-TCP通信程序"><a href="#第二章-TCP通信程序" class="headerlink" title="第二章 TCP通信程序"></a>第二章 TCP通信程序</h1><h2 id="2-1-概述"><a href="#2-1-概述" class="headerlink" title="2.1 概述"></a>2.1 概述</h2><p>TCP通信能实现两台计算机之间的数据交互，通信的两端，要严格区分为客户端（Client）与服务端（Server）。</p><p><strong>两端通信时步骤：</strong></p><ol><li>服务端程序，需要事先启动，等待客户端的连接。</li><li>客户端主动连接服务器端，连接成功才能通信。服务端不可以主动连接客户端。</li></ol><p><strong>在Java中，提供了两个类用于实现TCP通信程序：</strong></p><ol><li>客户端：<code>java.net.Socket</code> 类表示。创建<code>Socket</code>对象，向服务端发出连接请求，服务端响应请求，两者建立连接开始通信。</li><li>服务端：<code>java.net.ServerSocket</code> 类表示。创建<code>ServerSocket</code>对象，相当于开启一个服务，并等待客户端的连接。</li></ol><h2 id="2-2-Socket类"><a href="#2-2-Socket类" class="headerlink" title="2.2 Socket类"></a>2.2 Socket类</h2><p><code>Socket</code> 类：该类实现客户端套接字，套接字指的是两台设备之间通讯的端点。</p><h3 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><p><code>public Socket(String host, int port)</code> :创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null ，则相当于指定地址为回送地址。  </p><blockquote><p>小贴士：回送地址(127.x.x.x) 是本机回送地址（Loopback Address），主要用于网络软件测试以及本地机进程间通信，无论什么程序，一旦使用回送地址发送数据，立即返回，不进行任何网络传输。</p></blockquote></li></ul><p>构造举例，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Socket client = <span class="keyword">new</span> Socket(<span class="string">&quot;127.0.0.1&quot;</span>, <span class="number">6666</span>);</span><br></pre></td></tr></table></figure><h3 id="成员方法"><a href="#成员方法" class="headerlink" title="成员方法"></a>成员方法</h3><ul><li><p><code>public InputStream getInputStream()</code> ： 返回此套接字的输入流。</p><ul><li>如果此Scoket具有相关联的通道，则生成的InputStream 的所有操作也关联该通道。</li><li>关闭生成的InputStream也将关闭相关的Socket。</li></ul></li><li><p><code>public OutputStream getOutputStream()</code> ： 返回此套接字的输出流。</p><ul><li>如果此Scoket具有相关联的通道，则生成的OutputStream 的所有操作也关联该通道。</li><li>关闭生成的OutputStream也将关闭相关的Socket。</li></ul></li><li><p><code>public void close()</code> ：关闭此套接字。</p><ul><li>一旦一个socket被关闭，它不可再使用。</li><li>关闭此socket也将关闭相关的InputStream和OutputStream 。 </li></ul></li><li><p><code>public void shutdownOutput()</code> ： 禁用此套接字的输出流。   </p><ul><li>任何先前写出的数据将被发送，随后终止输出流。 </li></ul><h2 id="2-3-ServerSocket类"><a href="#2-3-ServerSocket类" class="headerlink" title="2.3 ServerSocket类"></a>2.3 ServerSocket类</h2></li></ul><p><code>ServerSocket</code>类：这个类实现了服务器套接字，该对象等待通过网络的请求。</p><h3 id="构造方法-1"><a href="#构造方法-1" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>public ServerSocket(int port)</code> ：使用该构造方法在创建ServerSocket对象时，就可以将其绑定到一个指定的端口号上，参数port就是端口号。</li></ul><p>构造举例，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ServerSocket server = <span class="keyword">new</span> ServerSocket(<span class="number">6666</span>);</span><br></pre></td></tr></table></figure><h3 id="成员方法-1"><a href="#成员方法-1" class="headerlink" title="成员方法"></a>成员方法</h3><ul><li><code>public Socket accept()</code> ：侦听并接受连接，返回一个新的Socket对象，用于和客户端实现通信。该方法会一直阻塞直到建立连接。 </li></ul><h2 id="2-4-简单的TCP网络程序"><a href="#2-4-简单的TCP网络程序" class="headerlink" title="2.4 简单的TCP网络程序"></a>2.4 简单的TCP网络程序</h2><h3 id="TCP通信分析图解"><a href="#TCP通信分析图解" class="headerlink" title="TCP通信分析图解"></a>TCP通信分析图解</h3><ol><li>【服务端】启动,创建ServerSocket对象，等待连接。</li><li>【客户端】启动,创建Socket对象，请求连接。</li><li>【服务端】接收连接,调用accept方法，并返回一个Socket对象。</li><li>【客户端】Socket对象，获取OutputStream，向服务端写出数据。</li><li>【服务端】Scoket对象，获取InputStream，读取客户端发送的数据。</li></ol><blockquote><p>到此，客户端向服务端发送数据成功。</p></blockquote><p><img src= "/img/loading.gif" data-lazy-src="img/5_%E7%AE%80%E5%8D%95%E9%80%9A%E4%BF%A1.jpg"></p><blockquote><p>自此，服务端向客户端回写数据。</p></blockquote><ol start="6"><li>【服务端】Socket对象，获取OutputStream，向客户端回写数据。</li><li>【客户端】Scoket对象，获取InputStream，解析回写数据。</li><li>【客户端】释放资源，断开连接。</li></ol><h3 id="客户端向服务器发送数据"><a href="#客户端向服务器发送数据" class="headerlink" title="客户端向服务器发送数据"></a>客户端向服务器发送数据</h3><p><strong>服务端实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ServerTCP</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;服务端启动 , 等待连接 .... &quot;</span>);</span><br><span class="line">        <span class="comment">// 1.创建 ServerSocket对象，绑定端口，开始等待连接</span></span><br><span class="line">        ServerSocket ss = <span class="keyword">new</span> ServerSocket(<span class="number">6666</span>);</span><br><span class="line">        <span class="comment">// 2.接收连接 accept 方法, 返回 socket 对象.</span></span><br><span class="line">        Socket server = ss.accept();</span><br><span class="line">        <span class="comment">// 3.通过socket 获取输入流</span></span><br><span class="line">        InputStream is = server.getInputStream();</span><br><span class="line">        <span class="comment">// 4.一次性读取数据</span></span><br><span class="line">      <span class="comment">// 4.1 创建字节数组</span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>];</span><br><span class="line">      <span class="comment">// 4.2 据读取到字节数组中.</span></span><br><span class="line">        <span class="keyword">int</span> len = is.read(b)；</span><br><span class="line">        <span class="comment">// 4.3 解析数组,打印字符串信息</span></span><br><span class="line">        String msg = <span class="keyword">new</span> String(b, <span class="number">0</span>, len);</span><br><span class="line">        System.out.println(msg);</span><br><span class="line">        <span class="comment">//5.关闭资源.</span></span><br><span class="line">        is.close();</span><br><span class="line">        server.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>客户端实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClientTCP</span> </span>&#123;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">System.out.println(<span class="string">&quot;客户端 发送数据&quot;</span>);</span><br><span class="line"><span class="comment">// 1.创建 Socket ( ip , port ) , 确定连接到哪里.</span></span><br><span class="line">Socket client = <span class="keyword">new</span> Socket(<span class="string">&quot;localhost&quot;</span>, <span class="number">6666</span>);</span><br><span class="line"><span class="comment">// 2.获取流对象 . 输出流</span></span><br><span class="line">OutputStream os = client.getOutputStream();</span><br><span class="line"><span class="comment">// 3.写出数据.</span></span><br><span class="line">os.write(<span class="string">&quot;你好么? tcp ,我来了&quot;</span>.getBytes());</span><br><span class="line"><span class="comment">// 4. 关闭资源 .</span></span><br><span class="line">os.close();</span><br><span class="line">client.close();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="服务器向客户端回写数据"><a href="#服务器向客户端回写数据" class="headerlink" title="服务器向客户端回写数据"></a>服务器向客户端回写数据</h3><p><strong>服务端实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ServerTCP</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;服务端启动 , 等待连接 .... &quot;</span>);</span><br><span class="line">        <span class="comment">// 1.创建 ServerSocket对象，绑定端口，开始等待连接</span></span><br><span class="line">        ServerSocket ss = <span class="keyword">new</span> ServerSocket(<span class="number">6666</span>);</span><br><span class="line">        <span class="comment">// 2.接收连接 accept 方法, 返回 socket 对象.</span></span><br><span class="line">        Socket server = ss.accept();</span><br><span class="line">        <span class="comment">// 3.通过socket 获取输入流</span></span><br><span class="line">        InputStream is = server.getInputStream();</span><br><span class="line">        <span class="comment">// 4.一次性读取数据</span></span><br><span class="line">      <span class="comment">// 4.1 创建字节数组</span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>];</span><br><span class="line">      <span class="comment">// 4.2 据读取到字节数组中.</span></span><br><span class="line">        <span class="keyword">int</span> len = is.read(b)；</span><br><span class="line">        <span class="comment">// 4.3 解析数组,打印字符串信息</span></span><br><span class="line">        String msg = <span class="keyword">new</span> String(b, <span class="number">0</span>, len);</span><br><span class="line">        System.out.println(msg);</span><br><span class="line">      <span class="comment">// =================回写数据=======================</span></span><br><span class="line">      <span class="comment">// 5. 通过 socket 获取输出流</span></span><br><span class="line">       OutputStream out = server.getOutputStream();</span><br><span class="line">      <span class="comment">// 6. 回写数据</span></span><br><span class="line">       out.write(<span class="string">&quot;我很好,谢谢你&quot;</span>.getBytes());</span><br><span class="line">      <span class="comment">// 7.关闭资源.</span></span><br><span class="line">      out.close();</span><br><span class="line">        is.close();</span><br><span class="line">        server.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>客户端实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClientTCP</span> </span>&#123;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">System.out.println(<span class="string">&quot;客户端 发送数据&quot;</span>);</span><br><span class="line"><span class="comment">// 1.创建 Socket ( ip , port ) , 确定连接到哪里.</span></span><br><span class="line">Socket client = <span class="keyword">new</span> Socket(<span class="string">&quot;localhost&quot;</span>, <span class="number">6666</span>);</span><br><span class="line"><span class="comment">// 2.通过Scoket,获取输出流对象 </span></span><br><span class="line">OutputStream os = client.getOutputStream();</span><br><span class="line"><span class="comment">// 3.写出数据.</span></span><br><span class="line">os.write(<span class="string">&quot;你好么? tcp ,我来了&quot;</span>.getBytes());</span><br><span class="line">      <span class="comment">// ==============解析回写=========================</span></span><br><span class="line">      <span class="comment">// 4. 通过Scoket,获取 输入流对象</span></span><br><span class="line">      InputStream in = client.getInputStream();</span><br><span class="line">      <span class="comment">// 5. 读取数据数据</span></span><br><span class="line">      <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">100</span>];</span><br><span class="line">      <span class="keyword">int</span> len = in.read(b);</span><br><span class="line">      System.out.println(<span class="keyword">new</span> String(b, <span class="number">0</span>, len));</span><br><span class="line"><span class="comment">// 6. 关闭资源 .</span></span><br><span class="line">      in.close();</span><br><span class="line">os.close();</span><br><span class="line">client.close();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第三章-综合案例"><a href="#第三章-综合案例" class="headerlink" title="第三章 综合案例"></a>第三章 综合案例</h1><h2 id="3-1-文件上传案例"><a href="#3-1-文件上传案例" class="headerlink" title="3.1 文件上传案例"></a>3.1 文件上传案例</h2><h3 id="文件上传分析图解"><a href="#文件上传分析图解" class="headerlink" title="文件上传分析图解"></a>文件上传分析图解</h3><ol><li>【客户端】输入流，从硬盘读取文件数据到程序中。</li><li>【客户端】输出流，写出文件数据到服务端。</li><li>【服务端】输入流，读取文件数据到服务端程序。</li><li>【服务端】输出流，写出文件数据到服务器硬盘中。</li></ol><p><img src= "/img/loading.gif" data-lazy-src="img/6_upload.jpg">    </p><h4 id="基本实现"><a href="#基本实现" class="headerlink" title="基本实现"></a>基本实现</h4><p><strong>服务端实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileUpload_Server</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;服务器 启动.....  &quot;</span>);</span><br><span class="line">        <span class="comment">// 1. 创建服务端ServerSocket</span></span><br><span class="line">      ServerSocket serverSocket = <span class="keyword">new</span> ServerSocket(<span class="number">6666</span>);</span><br><span class="line">  <span class="comment">// 2. 建立连接 </span></span><br><span class="line">        Socket accept = serverSocket.accept();</span><br><span class="line">      <span class="comment">// 3. 创建流对象</span></span><br><span class="line">      <span class="comment">// 3.1 获取输入流,读取文件数据</span></span><br><span class="line">        BufferedInputStream bis = <span class="keyword">new</span> BufferedInputStream(accept.getInputStream());</span><br><span class="line">        <span class="comment">// 3.2 创建输出流,保存到本地 .</span></span><br><span class="line">        BufferedOutputStream bos = <span class="keyword">new</span> BufferedOutputStream(<span class="keyword">new</span> FileOutputStream(<span class="string">&quot;copy.jpg&quot;</span>));</span><br><span class="line"><span class="comment">// 4. 读写数据</span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span> * <span class="number">8</span>];</span><br><span class="line">        <span class="keyword">int</span> len;</span><br><span class="line">        <span class="keyword">while</span> ((len = bis.read(b)) != -<span class="number">1</span>) &#123;</span><br><span class="line">            bos.write(b, <span class="number">0</span>, len);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//5. 关闭 资源</span></span><br><span class="line">        bos.close();</span><br><span class="line">        bis.close();</span><br><span class="line">        accept.close();</span><br><span class="line">        System.out.println(<span class="string">&quot;文件上传已保存&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>客户端实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileUPload_Client</span> </span>&#123;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 1.创建流对象</span></span><br><span class="line">        <span class="comment">// 1.1 创建输入流,读取本地文件  </span></span><br><span class="line">        BufferedInputStream bis  = <span class="keyword">new</span> BufferedInputStream(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;test.jpg&quot;</span>));</span><br><span class="line">        <span class="comment">// 1.2 创建输出流,写到服务端 </span></span><br><span class="line">        Socket socket = <span class="keyword">new</span> Socket(<span class="string">&quot;localhost&quot;</span>, <span class="number">6666</span>);</span><br><span class="line">        BufferedOutputStream   bos   = <span class="keyword">new</span> BufferedOutputStream(socket.getOutputStream());</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.写出数据. </span></span><br><span class="line">        <span class="keyword">byte</span>[] b  = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span> * <span class="number">8</span> ];</span><br><span class="line">        <span class="keyword">int</span> len ; </span><br><span class="line">        <span class="keyword">while</span> (( len  = bis.read(b))!=-<span class="number">1</span>) &#123;</span><br><span class="line">            bos.write(b, <span class="number">0</span>, len);</span><br><span class="line">            bos.flush();</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">&quot;文件发送完毕&quot;</span>);</span><br><span class="line">        <span class="comment">// 3.释放资源</span></span><br><span class="line"></span><br><span class="line">        bos.close(); </span><br><span class="line">        socket.close();</span><br><span class="line">        bis.close(); </span><br><span class="line">        System.out.println(<span class="string">&quot;文件上传完毕 &quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="文件上传优化分析"><a href="#文件上传优化分析" class="headerlink" title="文件上传优化分析"></a>文件上传优化分析</h3><ol><li><p><strong>文件名称写死的问题</strong></p><p>服务端，保存文件的名称如果写死，那么最终导致服务器硬盘，只会保留一个文件，建议使用系统时间优化，保证文件名称唯一，代码如下：</p></li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">FileOutputStream fis = <span class="keyword">new</span> FileOutputStream(System.currentTimeMillis()+<span class="string">&quot;.jpg&quot;</span>) <span class="comment">// 文件名称</span></span><br><span class="line">BufferedOutputStream bos = <span class="keyword">new</span> BufferedOutputStream(fis);</span><br></pre></td></tr></table></figure><ol start="2"><li><p><strong>循环接收的问题</strong></p><p>服务端，指保存一个文件就关闭了，之后的用户无法再上传，这是不符合实际的，使用循环改进，可以不断的接收不同用户的文件，代码如下：</p></li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 每次接收新的连接,创建一个Socket</span></span><br><span class="line"><span class="keyword">while</span>（<span class="keyword">true</span>）&#123;</span><br><span class="line">    Socket accept = serverSocket.accept();</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="3"><li><p><strong>效率问题</strong></p><p>服务端，在接收大文件时，可能耗费几秒钟的时间，此时不能接收其他用户上传，所以，使用多线程技术优化，代码如下：</p></li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span>（<span class="keyword">true</span>）&#123;</span><br><span class="line">    Socket accept = serverSocket.accept();</span><br><span class="line">    <span class="comment">// accept 交给子线程处理.</span></span><br><span class="line">    <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">      ......</span><br><span class="line">        InputStream bis = accept.getInputStream();</span><br><span class="line">      ......</span><br><span class="line">    &#125;).start();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="优化实现"><a href="#优化实现" class="headerlink" title="优化实现"></a>优化实现</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileUpload_Server</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;服务器 启动.....  &quot;</span>);</span><br><span class="line">        <span class="comment">// 1. 创建服务端ServerSocket</span></span><br><span class="line">        ServerSocket serverSocket = <span class="keyword">new</span> ServerSocket(<span class="number">6666</span>);</span><br><span class="line">      <span class="comment">// 2. 循环接收,建立连接</span></span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            Socket accept = serverSocket.accept();</span><br><span class="line">          <span class="comment">/* </span></span><br><span class="line"><span class="comment">          3. socket对象交给子线程处理,进行读写操作</span></span><br><span class="line"><span class="comment">               Runnable接口中,只有一个run方法,使用lambda表达式简化格式</span></span><br><span class="line"><span class="comment">            */</span></span><br><span class="line">            <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">                <span class="keyword">try</span> (</span><br><span class="line">                    <span class="comment">//3.1 获取输入流对象</span></span><br><span class="line">                    BufferedInputStream bis = <span class="keyword">new</span> BufferedInputStream(accept.getInputStream());</span><br><span class="line">                    <span class="comment">//3.2 创建输出流对象, 保存到本地 .</span></span><br><span class="line">                    FileOutputStream fis = <span class="keyword">new</span> FileOutputStream(System.currentTimeMillis() + <span class="string">&quot;.jpg&quot;</span>);</span><br><span class="line">                    BufferedOutputStream bos = <span class="keyword">new</span> BufferedOutputStream(fis);) &#123;</span><br><span class="line">                    <span class="comment">// 3.3 读写数据</span></span><br><span class="line">                    <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span> * <span class="number">8</span>];</span><br><span class="line">                    <span class="keyword">int</span> len;</span><br><span class="line">                    <span class="keyword">while</span> ((len = bis.read(b)) != -<span class="number">1</span>) &#123;</span><br><span class="line">                      bos.write(b, <span class="number">0</span>, len);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="comment">//4. 关闭 资源</span></span><br><span class="line">                    bos.close();</span><br><span class="line">                    bis.close();</span><br><span class="line">                    accept.close();</span><br><span class="line">                    System.out.println(<span class="string">&quot;文件上传已保存&quot;</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">                  e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="信息回写分析图解"><a href="#信息回写分析图解" class="headerlink" title="信息回写分析图解"></a>信息回写分析图解</h3><p>前四步与基本文件上传一致.</p><ol start="5"><li>【服务端】获取输出流，回写数据。</li><li>【客户端】获取输入流，解析回写数据。</li></ol><p><img src= "/img/loading.gif" data-lazy-src="img/6_upload2.jpg"></p><h4 id="回写实现"><a href="#回写实现" class="headerlink" title="回写实现"></a>回写实现</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileUpload_Server</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;服务器 启动.....  &quot;</span>);</span><br><span class="line">        <span class="comment">// 1. 创建服务端ServerSocket</span></span><br><span class="line">        ServerSocket serverSocket = <span class="keyword">new</span> ServerSocket(<span class="number">6666</span>);</span><br><span class="line">        <span class="comment">// 2. 循环接收,建立连接</span></span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            Socket accept = serverSocket.accept();</span><br><span class="line">          <span class="comment">/*</span></span><br><span class="line"><span class="comment">          3. socket对象交给子线程处理,进行读写操作</span></span><br><span class="line"><span class="comment">               Runnable接口中,只有一个run方法,使用lambda表达式简化格式</span></span><br><span class="line"><span class="comment">            */</span></span><br><span class="line">            <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">                <span class="keyword">try</span> (</span><br><span class="line">                    <span class="comment">//3.1 获取输入流对象</span></span><br><span class="line">                    BufferedInputStream bis = <span class="keyword">new</span> BufferedInputStream(accept.getInputStream());</span><br><span class="line">                    <span class="comment">//3.2 创建输出流对象, 保存到本地 .</span></span><br><span class="line">                    FileOutputStream fis = <span class="keyword">new</span> FileOutputStream(System.currentTimeMillis() + <span class="string">&quot;.jpg&quot;</span>);</span><br><span class="line">                    BufferedOutputStream bos = <span class="keyword">new</span> BufferedOutputStream(fis);</span><br><span class="line">                ) &#123;</span><br><span class="line">                    <span class="comment">// 3.3 读写数据</span></span><br><span class="line">                    <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span> * <span class="number">8</span>];</span><br><span class="line">                    <span class="keyword">int</span> len;</span><br><span class="line">                    <span class="keyword">while</span> ((len = bis.read(b)) != -<span class="number">1</span>) &#123;</span><br><span class="line">                        bos.write(b, <span class="number">0</span>, len);</span><br><span class="line">                    &#125;</span><br><span class="line"></span><br><span class="line">                    <span class="comment">// 4.=======信息回写===========================</span></span><br><span class="line">                    System.out.println(<span class="string">&quot;back ........&quot;</span>);</span><br><span class="line">                    OutputStream out = accept.getOutputStream();</span><br><span class="line">                    out.write(<span class="string">&quot;上传成功&quot;</span>.getBytes());</span><br><span class="line">                    out.close();</span><br><span class="line">                    <span class="comment">//================================</span></span><br><span class="line"></span><br><span class="line">                    <span class="comment">//5. 关闭 资源</span></span><br><span class="line">                    bos.close();</span><br><span class="line">                    bis.close();</span><br><span class="line">                    accept.close();</span><br><span class="line">                    System.out.println(<span class="string">&quot;文件上传已保存&quot;</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>客户端实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileUpload_Client</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 1.创建流对象</span></span><br><span class="line">        <span class="comment">// 1.1 创建输入流,读取本地文件</span></span><br><span class="line">        BufferedInputStream bis = <span class="keyword">new</span> BufferedInputStream(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;test.jpg&quot;</span>));</span><br><span class="line">        <span class="comment">// 1.2 创建输出流,写到服务端</span></span><br><span class="line">        Socket socket = <span class="keyword">new</span> Socket(<span class="string">&quot;localhost&quot;</span>, <span class="number">6666</span>);</span><br><span class="line">        BufferedOutputStream bos = <span class="keyword">new</span> BufferedOutputStream(socket.getOutputStream());</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.写出数据.</span></span><br><span class="line">        <span class="keyword">byte</span>[] b  = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span> * <span class="number">8</span> ];</span><br><span class="line">        <span class="keyword">int</span> len ;</span><br><span class="line">        <span class="keyword">while</span> (( len  = bis.read(b))!=-<span class="number">1</span>) &#123;</span><br><span class="line">            bos.write(b, <span class="number">0</span>, len);</span><br><span class="line">        &#125;</span><br><span class="line">      <span class="comment">// 关闭输出流,通知服务端,写出数据完毕</span></span><br><span class="line">        socket.shutdownOutput();</span><br><span class="line">        System.out.println(<span class="string">&quot;文件发送完毕&quot;</span>);</span><br><span class="line">        <span class="comment">// 3. =====解析回写============</span></span><br><span class="line">        InputStream in = socket.getInputStream();</span><br><span class="line">        <span class="keyword">byte</span>[] back = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">20</span>];</span><br><span class="line">        in.read(back);</span><br><span class="line">        System.out.println(<span class="keyword">new</span> String(back));</span><br><span class="line">        in.close();</span><br><span class="line">        <span class="comment">// ============================</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 4.释放资源</span></span><br><span class="line">        socket.close();</span><br><span class="line">        bis.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-2-模拟B-S服务器-扩展知识点"><a href="#3-2-模拟B-S服务器-扩展知识点" class="headerlink" title="3.2 模拟B\S服务器(扩展知识点)"></a>3.2 模拟B\S服务器(扩展知识点)</h2><p>模拟网站服务器，使用浏览器访问自己编写的服务端程序，查看网页效果。</p><h3 id="案例分析"><a href="#案例分析" class="headerlink" title="案例分析"></a>案例分析</h3><ol><li><p>准备页面数据，web文件夹。</p><p>复制到我们Module中，比如复制到day08中</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E5%A4%8D%E5%88%B6.png"></p></li><li><p>我们模拟服务器端，ServerSocket类监听端口，使用浏览器访问</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">    ServerSocket server = <span class="keyword">new</span> ServerSocket(<span class="number">8000</span>);</span><br><span class="line">    Socket socket = server.accept();</span><br><span class="line">    InputStream in = socket.getInputStream();</span><br><span class="line">       <span class="keyword">byte</span>[] bytes = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>];</span><br><span class="line">    <span class="keyword">int</span> len = in.read(bytes);</span><br><span class="line">    System.out.println(<span class="keyword">new</span> String(bytes,<span class="number">0</span>,len));</span><br><span class="line">    socket.close();</span><br><span class="line">    server.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E6%97%A0%E6%B3%95%E8%AE%BF%E9%97%AE.jpg"></p></li><li><p>服务器程序中字节输入流可以读取到浏览器发来的请求信息</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E8%AF%BB%E5%8F%96%E8%AE%BF%E9%97%AE%E4%BF%A1%E6%81%AF.jpg"></p></li></ol><p>GET/web/index.html HTTP/1.1是浏览器的请求消息。/web/index.html为浏览器想要请求的服务器端的资源,使用字符串切割方式获取到请求的资源。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//转换流,读取浏览器请求第一行</span></span><br><span class="line">BufferedReader readWb = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> InputStreamReader(socket.getInputStream()));</span><br><span class="line">String requst = readWb.readLine();</span><br><span class="line"><span class="comment">//取出请求资源的路径</span></span><br><span class="line">String[] strArr = requst.split(<span class="string">&quot; &quot;</span>);</span><br><span class="line"><span class="comment">//去掉web前面的/</span></span><br><span class="line">String path = strArr[<span class="number">1</span>].substring(<span class="number">1</span>);</span><br><span class="line">System.out.println(path);</span><br></pre></td></tr></table></figure><h3 id="案例实现"><a href="#案例实现" class="headerlink" title="案例实现"></a>案例实现</h3><p>服务端实现：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SerDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;服务端  启动 , 等待连接 .... &quot;</span>);</span><br><span class="line">        <span class="comment">// 创建ServerSocket 对象</span></span><br><span class="line">        ServerSocket server = <span class="keyword">new</span> ServerSocket(<span class="number">8888</span>);</span><br><span class="line">        Socket socket = server.accept();</span><br><span class="line">        <span class="comment">// 转换流读取浏览器的请求消息</span></span><br><span class="line">        BufferedReader readWb = <span class="keyword">new</span></span><br><span class="line">        BufferedReader(<span class="keyword">new</span> InputStreamReader(socket.getInputStream()));</span><br><span class="line">        String requst = readWb.readLine();</span><br><span class="line">        <span class="comment">// 取出请求资源的路径</span></span><br><span class="line">        String[] strArr = requst.split(<span class="string">&quot; &quot;</span>);</span><br><span class="line">        <span class="comment">// 去掉web前面的/</span></span><br><span class="line">        String path = strArr[<span class="number">1</span>].substring(<span class="number">1</span>);</span><br><span class="line">        <span class="comment">// 读取客户端请求的资源文件</span></span><br><span class="line">        FileInputStream fis = <span class="keyword">new</span> FileInputStream(path);</span><br><span class="line">        <span class="keyword">byte</span>[] bytes= <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>];</span><br><span class="line">        <span class="keyword">int</span> len = <span class="number">0</span> ;</span><br><span class="line">        <span class="comment">// 字节输出流,将文件写会客户端</span></span><br><span class="line">        OutputStream out = socket.getOutputStream();</span><br><span class="line">        <span class="comment">// 写入HTTP协议响应头,固定写法</span></span><br><span class="line">        out.write(<span class="string">&quot;HTTP/1.1 200 OK\r\n&quot;</span>.getBytes());</span><br><span class="line">        out.write(<span class="string">&quot;Content-Type:text/html\r\n&quot;</span>.getBytes());</span><br><span class="line">        <span class="comment">// 必须要写入空行,否则浏览器不解析</span></span><br><span class="line">        out.write(<span class="string">&quot;\r\n&quot;</span>.getBytes());</span><br><span class="line">        <span class="keyword">while</span>((len = fis.read(bytes))!=-<span class="number">1</span>)&#123;</span><br><span class="line">            out.write(bytes,<span class="number">0</span>,len);</span><br><span class="line">        &#125;</span><br><span class="line">        fis.close();</span><br><span class="line">        out.close();</span><br><span class="line">        readWb.close();</span><br><span class="line">        socket.close();</span><br><span class="line">        server.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="访问效果"><a href="#访问效果" class="headerlink" title="访问效果"></a>访问效果</h3><ul><li><strong>火狐</strong></li></ul><p><img src= "/img/loading.gif" data-lazy-src="img/%E6%95%88%E6%9E%9C%E5%9B%BE1.png"></p><blockquote><p>小贴士：不同的浏览器，内核不一样，解析效果有可能不一样。</p></blockquote><p>发现浏览器中出现很多的叉子,说明浏览器没有读取到图片信息导致。</p><p>浏览器工作原理是遇到图片会开启一个线程进行单独的访问,因此在服务器端加入线程技术。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ServerDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        ServerSocket server = <span class="keyword">new</span> ServerSocket(<span class="number">8888</span>);</span><br><span class="line">        <span class="keyword">while</span>(<span class="keyword">true</span>)&#123;</span><br><span class="line">            Socket socket = server.accept();</span><br><span class="line">            <span class="keyword">new</span> Thread(<span class="keyword">new</span> Web(socket)).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Web</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123;</span><br><span class="line">        <span class="keyword">private</span> Socket socket;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">Web</span><span class="params">(Socket socket)</span></span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.socket=socket;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">try</span>&#123;</span><br><span class="line">                <span class="comment">//转换流,读取浏览器请求第一行</span></span><br><span class="line">                BufferedReader readWb = <span class="keyword">new</span></span><br><span class="line">                        BufferedReader(<span class="keyword">new</span> InputStreamReader(socket.getInputStream()));</span><br><span class="line">                String requst = readWb.readLine();</span><br><span class="line">                <span class="comment">//取出请求资源的路径</span></span><br><span class="line">                String[] strArr = requst.split(<span class="string">&quot; &quot;</span>);</span><br><span class="line">                System.out.println(Arrays.toString(strArr));</span><br><span class="line">                String path = strArr[<span class="number">1</span>].substring(<span class="number">1</span>);</span><br><span class="line">                System.out.println(path);</span><br><span class="line"></span><br><span class="line">                FileInputStream fis = <span class="keyword">new</span> FileInputStream(path);</span><br><span class="line">                System.out.println(fis);</span><br><span class="line">                <span class="keyword">byte</span>[] bytes= <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>];</span><br><span class="line">                <span class="keyword">int</span> len = <span class="number">0</span> ;</span><br><span class="line">                <span class="comment">//向浏览器 回写数据</span></span><br><span class="line">                OutputStream out = socket.getOutputStream();</span><br><span class="line">                out.write(<span class="string">&quot;HTTP/1.1 200 OK\r\n&quot;</span>.getBytes());</span><br><span class="line">                out.write(<span class="string">&quot;Content-Type:text/html\r\n&quot;</span>.getBytes());</span><br><span class="line">                out.write(<span class="string">&quot;\r\n&quot;</span>.getBytes());</span><br><span class="line">                <span class="keyword">while</span>((len = fis.read(bytes))!=-<span class="number">1</span>)&#123;</span><br><span class="line">                    out.write(bytes,<span class="number">0</span>,len);</span><br><span class="line">                &#125;</span><br><span class="line">                fis.close();</span><br><span class="line">                out.close();</span><br><span class="line">                readWb.close();</span><br><span class="line">                socket.close();</span><br><span class="line">            &#125;<span class="keyword">catch</span>(Exception ex)&#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>访问效果：</strong></p><p><img src= "/img/loading.gif" data-lazy-src="img/%E6%95%88%E6%9E%9C%E5%9B%BE2.png">图解：</p><p><img src= "/img/loading.gif" data-lazy-src="img%5CBS%E9%80%9A%E4%BF%A1.bmp"></p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记14-软件开发流程&amp;设计原则</title>
      <link href="java/javase/note/note14/"/>
      <url>java/javase/note/note14/</url>
      
        <content type="html"><![CDATA[<h2 id="今天内容"><a href="#今天内容" class="headerlink" title="今天内容:"></a>今天内容:</h2><ul><li>1.常用的设计原则</li><li>2.常用的设计模式</li><li>3.常用的查找算法</li><li>4.常用的排序算法</li></ul><h2 id="1-常用的设计原则-记住"><a href="#1-常用的设计原则-记住" class="headerlink" title="1.常用的设计原则(记住)"></a>1.常用的设计原则(记住)</h2><h3 id="1-1软件的开发流程"><a href="#1-1软件的开发流程" class="headerlink" title="1.1软件的开发流程"></a>1.1软件的开发流程</h3><pre><code>软件开发授权-投标 -&gt; 100万1. 编写需求分析文档 =&gt; 2. 概要设计文档(架构) =&gt; 3. 详细设计文档(类图) =&gt; 4. 编码(项目经理分具体任务)    还要测试  (SVN/GIT)单元测试,模块测试(一般都是美女多一些,对于技术要求比较低) 黑盒测试 白盒测试5. 安装和调试    写使用说明文档6. 维护和升级    软件公司和客户协商(钱要到位)    还有一锤子买卖的(就是不管维护那种)    如果整个开发周期是半年(可能编码只占一个月的时间)架构师把架构架构错了,那就都白干了,重新架构意味着要加班,这种情况不多,因为架构师至少要5年以上经验的绝大多是是客户的需求问题,或者是客户要加功能.</code></pre><h3 id="1-2常用的设计原则"><a href="#1-2常用的设计原则" class="headerlink" title="1.2常用的设计原则"></a>1.2常用的设计原则</h3><h3 id="1-开放封闭原则-Open-Close-Principe"><a href="#1-开放封闭原则-Open-Close-Principe" class="headerlink" title="1. 开放封闭原则(Open Close Principe)"></a>1. 开放封闭原则(Open Close Principe)</h3><p>对于扩展开放,对于修改关闭,为了使程序的扩展性好,易于维护<br>如:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span>  <span class="class"><span class="keyword">class</span>  <span class="title">Person</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">boolean</span> gender;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>不,这样前面美女测试人呢的工作就白做了,所以应该这样</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span>  <span class="class"><span class="keyword">class</span>  <span class="title">Person</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SubPerson</span> <span class="keyword">extends</span> <span class="title">Person</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">boolean</span> gender;</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="2-里氏代换原则-Liskov-Substitution-Principe"><a href="#2-里氏代换原则-Liskov-Substitution-Principe" class="headerlink" title="2. 里氏代换原则(Liskov Substitution Principe)"></a>2. 里氏代换原则(Liskov Substitution Principe)</h3><ul><li><p>任何父类可以出现的地方,子类一定可以出现</p></li><li><p>子类is a 父类</p></li><li><p>在以后的开发中多使用继承和多态的理念</p><p>  多态的实际意义:</p><pre><code>  屏蔽不同子类的差异性,实现通用的编程,产生不同的结果</code></pre><p>  如:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> statie <span class="keyword">void</span> <span class="title">draw</span><span class="params">(Shape s)</span></span>&#123;</span><br><span class="line">    s.show();</span><br><span class="line">&#125;</span><br><span class="line">ShapeTest.draw(<span class="keyword">new</span> Rect(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>));</span><br><span class="line">ShapeTest.draw(<span class="keyword">new</span> Circle(<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>));</span><br><span class="line"><span class="comment">// 父类类型的引用能到的地方,子类的引用也能到</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="3-依赖倒转原则-Dependence-Inversion-Principle"><a href="#3-依赖倒转原则-Dependence-Inversion-Principle" class="headerlink" title="3.依赖倒转原则(Dependence Inversion Principle)"></a>3.依赖倒转原则(Dependence Inversion Principle)</h3><p>尽量多依赖于抽象类或接口而不是具体实现类,对子类具有强制性和规范性<br>如:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">publice <span class="class"><span class="keyword">class</span> <span class="title">Account</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">getLix</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">// ...        </span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">publice <span class="class"><span class="keyword">class</span> <span class="title">FixedAccount</span> <span class="keyword">extends</span> <span class="title">Account</span></span>&#123;</span><br><span class="line">    <span class="comment">//我这里想重写就重写,以为我的父类也不是抽象的 </span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>要是这样,就符合了 </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">publice <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Account</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">double</span> <span class="title">getLix</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">// ...        </span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">publice <span class="class"><span class="keyword">class</span> <span class="title">FixedAccount</span> <span class="keyword">extends</span> <span class="title">Account</span></span>&#123;</span><br><span class="line">    <span class="comment">// 这回就不得不继承了</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">getLixi</span><span class="params">()</span></span>&#123;&#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="4-接口隔离原则-interface-segregation-principle"><a href="#4-接口隔离原则-interface-segregation-principle" class="headerlink" title="4.接口隔离原则(interface segregation principle)"></a>4.接口隔离原则(interface segregation principle)</h3><ul><li>尽量依赖于小接口而不是大接口,避免接口的污染</li><li>可以降低耦合度</li><li>耦合主要指一个模块于其他模块之间的关联度.</li></ul><p>如:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Animal</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>;<span class="comment">//描述奔跑 行为</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">()</span></span>; <span class="comment">//描述飞行行为</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">implements</span> <span class="title">Animal</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>&#123;...&#125;;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="comment">//        这个方法没法写了</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="5-迪米特法则-最少知道原则-Demeter-Principe"><a href="#5-迪米特法则-最少知道原则-Demeter-Principe" class="headerlink" title="5.迪米特法则(最少知道原则) (Demeter Principe)"></a>5.迪米特法则(最少知道原则) (Demeter Principe)</h3><ul><li>一个实体应当尽量少于其他实体之间 发生相互作用</li><li>低耦合,高内聚</li><li>高内聚就是指将一个实体应当将该实体应该拥有的功能尽量聚集在该实体内部</li></ul><h3 id="6-合成复用原则-Composite-Reuse-Principe"><a href="#6-合成复用原则-Composite-Reuse-Principe" class="headerlink" title="6.合成复用原则(Composite Reuse Principe)"></a>6.合成复用原则(Composite Reuse Principe)</h3><ul><li>尽量多使用合成的方式,而不是继承的方式.<br>如:<pre><code class="java">public class A&#123;  public void show()&#123;...&#125;  ... ...&#125;public class B extends A&#123;  public void test()&#123;      // 调用show方法      show();  &#125;  ... ...  // 这样不推荐,因为java只能单继承,或者说会影响调用show()方法时候的性能,因为继承会继承父类的所有方法&#125;</code></pre>升级版<pre><code class="java">public class A&#123;  public void show()&#123;...&#125;  ... ...&#125;public class B&#123;  private A a;  public void test()&#123;      // 调用show方法      a.show()  &#125;  ... ...  // 这样不推荐,因为java只能单继承,或者说会影响调用show()方法时候的性能,因为继承会继承父类的所有方法&#125;</code></pre></li></ul><h3 id="2常用设计模式"><a href="#2常用设计模式" class="headerlink" title="2常用设计模式"></a>2常用设计模式</h3><p>2.1 基本概念</p><ul><li>设计模式是一套被反复使用,多数人知晓的,经过分类编目的,设计经验的总结.</li><li>设计模式就是一种用于固定场合的固定套路</li></ul><p>2.2 常用设计模式<br>单例设计模式</p><p>模板设计模式</p><p>工厂方法模式:<br>    当你需要大量创建对象的时候,你就需要创建一个工厂类,然后创建一个工程方法, 这样可以提高程序的可维护性和扩展性</p><p>抽象工厂模式    </p><h3 id="3-常用的查找算法"><a href="#3-常用的查找算法" class="headerlink" title="3.常用的查找算法()"></a>3.常用的查找算法()</h3><ul><li><p>3.1线性查找算法(重中之重)</p></li><li><p>3.2折半查找算法</p></li></ul><h3 id="4-常用的排序算法"><a href="#4-常用的排序算法" class="headerlink" title="4.常用的排序算法"></a>4.常用的排序算法</h3><p>冒泡排序算法</p><p>比较相邻位置的两个元素,若第一个元素比第二个元素大则交换;</p><p>从开始的第一对元素一直到结尾的最后一对元素,经过这一轮找到了最大值并放在了最后;</p><p>持续对越来越少的元素进行量量比较,直到所有元素不再发生交换为止;</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jupyter浅析</title>
      <link href="python/base/python-jupyter/"/>
      <url>python/base/python-jupyter/</url>
      
        <content type="html"><![CDATA[<h3 id="一、jupyter-起步-简介"><a href="#一、jupyter-起步-简介" class="headerlink" title="一、jupyter 起步:简介"></a>一、jupyter 起步:简介</h3><p>Jupyter Notebook是一个开源的Web应用程序，允许用户创建和共享包含代码、方程式、可视化和文本的文档。它的用途包括：数据清理和转换、数值模拟、统计建模、数据可视化、机器学习等等。它具有以下优势：</p><p>可选择语言：支持超过40种编程语言，包括Python、R、Julia、Scala等。<br>分享笔记本：可以使用电子邮件、Dropbox、GitHub和Jupyter Notebook Viewer与他人共享。<br>交互式输出：代码可以生成丰富的交互式输出，包括HTML、图像、视频、LaTeX等等。<br>大数据整合：通过Python、R、Scala编程语言使用Apache Spark等大数据框架工具。支持使用pandas、scikit-learn、ggplot2、TensorFlow来探索同一份数据。</p><h3 id="二、安装与运行"><a href="#二、安装与运行" class="headerlink" title="二、安装与运行"></a>二、安装与运行</h3><p>虽然Jupyter可以运行多种编程语言，但Python是安装Jupyter Noterbook的必备条件（Python2.7，或Python3.3以上）。有两种安装方式：使用Anaconda安装或使用pip命令安装。关于安装的全部信息可以在官网读到：安装Jupyter。</p><h4 id="2-1使用Anaconda安装"><a href="#2-1使用Anaconda安装" class="headerlink" title="2.1使用Anaconda安装"></a>2.1使用Anaconda安装</h4><p>对于小白，强烈建议使用Anaconda发行版安装Python和Jupyter，其中包括Python、Jupyter Notebook和其他常用的科学计算和数据科学软件包。</p><p>首先，下载Anaconda。建议下载Anaconda的最新Python 3版本。其次，请按照下载页面上的说明安装下载的Anaconda版本。最后，安装成功！</p><h4 id="2-2使用pip命令安装"><a href="#2-2使用pip命令安装" class="headerlink" title="2.2使用pip命令安装"></a>2.2使用pip命令安装</h4><p>对于有经验的Python用户，可以使用Python的包管理器pip而不是Anaconda 来安装Jupyter。</p><p>如果已经安装了Python3：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">python3 -m pip install --upgrade pip</span><br><span class="line">python3 -m pip install jupyter</span><br></pre></td></tr></table></figure><p>如果已经安装了Python2：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">python -m pip install --upgrade pip</span><br><span class="line">python -m pip install jupyter</span><br></pre></td></tr></table></figure><p>恭喜，你已经成功安装好了！</p><h4 id="2-3运行Jupyter-Notebook"><a href="#2-3运行Jupyter-Notebook" class="headerlink" title="2.3运行Jupyter Notebook"></a>2.3运行Jupyter Notebook</h4><p>成功安装Jupyter Notebook后，在Terminal (Mac / Linux)或Command Prompt(Windows)中运行以下命令就可打开Jupyter Notebook。</p><p>jupyter notebook </p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中缓冲流、转换流、序列化流</title>
      <link href="java/javaold/cushion/"/>
      <url>java/javaold/cushion/</url>
      
        <content type="html"><![CDATA[<h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li> 缓冲流</li><li> 转换流</li><li> 序列化流</li><li> 打印流</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><ul><li><input checked="" disabled="" type="checkbox"> 能够使用字节缓冲流读取数据到程序</li><li><input checked="" disabled="" type="checkbox"> 能够使用字节缓冲流写出数据到文件</li><li><input disabled="" type="checkbox"> 能够明确字符缓冲流的作用和基本用法</li><li><input disabled="" type="checkbox"> 能够使用缓冲流的特殊功能</li><li><input disabled="" type="checkbox"> 能够阐述编码表的意义</li><li><input disabled="" type="checkbox"> 能够使用转换流读取指定编码的文本文件</li><li><input disabled="" type="checkbox"> 能够使用转换流写入指定编码的文本文件</li><li><input disabled="" type="checkbox"> 能够说出打印流的特点</li><li><input checked="" disabled="" type="checkbox"> 能够使用序列化流写出对象到文件</li><li><input checked="" disabled="" type="checkbox"> 能够使用反序列化流读取文件到程序中</li></ul><h1 id="第一章-缓冲流"><a href="#第一章-缓冲流" class="headerlink" title="第一章 缓冲流"></a>第一章 缓冲流</h1><p>昨天学习了基本的一些流，作为IO流的入门，今天我们要见识一些更强大的流。比如能够高效读写的缓冲流，能够转换编码的转换流，能够持久化存储对象的序列化流等等。这些功能更为强大的流，都是在基本的流对象基础之上创建而来的，就像穿上铠甲的武士一样，相当于是对基本流对象的一种增强。</p><h2 id="1-1-概述"><a href="#1-1-概述" class="headerlink" title="1.1 概述"></a>1.1 概述</h2><p>缓冲流,也叫高效流，是对4个基本的<code>FileXxx</code> 流的增强，所以也是4个流，按照数据类型分类：</p><ul><li><strong>字节缓冲流</strong>：<code>BufferedInputStream</code>，<code>BufferedOutputStream</code> </li><li><strong>字符缓冲流</strong>：<code>BufferedReader</code>，<code>BufferedWriter</code></li></ul><p>缓冲流的基本原理，是在创建流对象时，会创建一个内置的默认大小的缓冲区数组，通过缓冲区读写，减少系统IO次数，从而提高读写的效率。</p><h2 id="1-2-字节缓冲流"><a href="#1-2-字节缓冲流" class="headerlink" title="1.2 字节缓冲流"></a>1.2 字节缓冲流</h2><h3 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>public BufferedInputStream(InputStream in)</code> ：创建一个 新的缓冲输入流。 </li><li><code>public BufferedOutputStream(OutputStream out)</code>： 创建一个新的缓冲输出流。</li></ul><p>构造举例，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建字节缓冲输入流</span></span><br><span class="line">BufferedInputStream bis = <span class="keyword">new</span> BufferedInputStream(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;bis.txt&quot;</span>));</span><br><span class="line"><span class="comment">// 创建字节缓冲输出流</span></span><br><span class="line">BufferedOutputStream bos = <span class="keyword">new</span> BufferedOutputStream(<span class="keyword">new</span> FileOutputStream(<span class="string">&quot;bos.txt&quot;</span>));</span><br></pre></td></tr></table></figure><h3 id="效率测试"><a href="#效率测试" class="headerlink" title="效率测试"></a>效率测试</h3><p>查询API，缓冲流读写方法与基本的流是一致的，我们通过复制大文件（375MB），测试它的效率。</p><ol><li>基本流，代码如下：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BufferedDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        <span class="comment">// 记录开始时间</span></span><br><span class="line">        <span class="keyword">long</span> start = System.currentTimeMillis();</span><br><span class="line">        <span class="comment">// 创建流对象</span></span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">            FileInputStream fis = <span class="keyword">new</span> FileInputStream(<span class="string">&quot;jdk9.exe&quot;</span>);</span><br><span class="line">            FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;copy.exe&quot;</span>)</span><br><span class="line">        )&#123;</span><br><span class="line">            <span class="comment">// 读写数据</span></span><br><span class="line">            <span class="keyword">int</span> b;</span><br><span class="line">            <span class="keyword">while</span> ((b = fis.read()) != -<span class="number">1</span>) &#123;</span><br><span class="line">                fos.write(b);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 记录结束时间</span></span><br><span class="line">        <span class="keyword">long</span> end = System.currentTimeMillis();</span><br><span class="line">        System.out.println(<span class="string">&quot;普通流复制时间:&quot;</span>+(end - start)+<span class="string">&quot; 毫秒&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">十几分钟过去了...</span><br></pre></td></tr></table></figure><ol start="2"><li>缓冲流，代码如下：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BufferedDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        <span class="comment">// 记录开始时间</span></span><br><span class="line">        <span class="keyword">long</span> start = System.currentTimeMillis();</span><br><span class="line">        <span class="comment">// 创建流对象</span></span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">            BufferedInputStream bis = <span class="keyword">new</span> BufferedInputStream(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;jdk9.exe&quot;</span>));</span><br><span class="line">         BufferedOutputStream bos = <span class="keyword">new</span> BufferedOutputStream(<span class="keyword">new</span> FileOutputStream(<span class="string">&quot;copy.exe&quot;</span>));</span><br><span class="line">        )&#123;</span><br><span class="line">        <span class="comment">// 读写数据</span></span><br><span class="line">            <span class="keyword">int</span> b;</span><br><span class="line">            <span class="keyword">while</span> ((b = bis.read()) != -<span class="number">1</span>) &#123;</span><br><span class="line">                bos.write(b);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 记录结束时间</span></span><br><span class="line">        <span class="keyword">long</span> end = System.currentTimeMillis();</span><br><span class="line">        System.out.println(<span class="string">&quot;缓冲流复制时间:&quot;</span>+(end - start)+<span class="string">&quot; 毫秒&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">缓冲流复制时间:<span class="number">8016</span> 毫秒</span><br></pre></td></tr></table></figure><p>如何更快呢？</p><p>使用数组的方式，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BufferedDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        <span class="comment">// 记录开始时间</span></span><br><span class="line">        <span class="keyword">long</span> start = System.currentTimeMillis();</span><br><span class="line">        <span class="comment">// 创建流对象</span></span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">            BufferedInputStream bis = <span class="keyword">new</span> BufferedInputStream(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;jdk9.exe&quot;</span>));</span><br><span class="line">         BufferedOutputStream bos = <span class="keyword">new</span> BufferedOutputStream(<span class="keyword">new</span> FileOutputStream(<span class="string">&quot;copy.exe&quot;</span>));</span><br><span class="line">        )&#123;</span><br><span class="line">            <span class="comment">// 读写数据</span></span><br><span class="line">            <span class="keyword">int</span> len;</span><br><span class="line">            <span class="keyword">byte</span>[] bytes = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">8</span>*<span class="number">1024</span>];</span><br><span class="line">            <span class="keyword">while</span> ((len = bis.read(bytes)) != -<span class="number">1</span>) &#123;</span><br><span class="line">                bos.write(bytes, <span class="number">0</span> , len);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 记录结束时间</span></span><br><span class="line">        <span class="keyword">long</span> end = System.currentTimeMillis();</span><br><span class="line">        System.out.println(<span class="string">&quot;缓冲流使用数组复制时间:&quot;</span>+(end - start)+<span class="string">&quot; 毫秒&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">缓冲流使用数组复制时间:<span class="number">666</span> 毫秒</span><br></pre></td></tr></table></figure><h2 id="1-3-字符缓冲流"><a href="#1-3-字符缓冲流" class="headerlink" title="1.3 字符缓冲流"></a>1.3 字符缓冲流</h2><h3 id="构造方法-1"><a href="#构造方法-1" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>public BufferedReader(Reader in)</code> ：创建一个 新的缓冲输入流。 </li><li><code>public BufferedWriter(Writer out)</code>： 创建一个新的缓冲输出流。</li></ul><p>构造举例，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建字符缓冲输入流</span></span><br><span class="line">BufferedReader br = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">&quot;br.txt&quot;</span>));</span><br><span class="line"><span class="comment">// 创建字符缓冲输出流</span></span><br><span class="line">BufferedWriter bw = <span class="keyword">new</span> BufferedWriter(<span class="keyword">new</span> FileWriter(<span class="string">&quot;bw.txt&quot;</span>));</span><br></pre></td></tr></table></figure><h3 id="特有方法"><a href="#特有方法" class="headerlink" title="特有方法"></a>特有方法</h3><p>字符缓冲流的基本方法与普通字符流调用方式一致，不再阐述，我们来看它们具备的特有方法。</p><ul><li>BufferedReader：<code>public String readLine()</code>: 读一行文字。 </li><li>BufferedWriter：<code>public void newLine()</code>: 写一行行分隔符,由系统属性定义符号。 </li></ul><p><code>readLine</code>方法演示，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BufferedReaderDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">         <span class="comment">// 创建流对象</span></span><br><span class="line">        BufferedReader br = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">&quot;in.txt&quot;</span>));</span><br><span class="line">        <span class="comment">// 定义字符串,保存读取的一行文字</span></span><br><span class="line">        String line  = <span class="keyword">null</span>;</span><br><span class="line">        <span class="comment">// 循环读取,读取到最后返回null</span></span><br><span class="line">        <span class="keyword">while</span> ((line = br.readLine())!=<span class="keyword">null</span>) &#123;</span><br><span class="line">            System.out.print(line);</span><br><span class="line">            System.out.println(<span class="string">&quot;------&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 释放资源</span></span><br><span class="line">        br.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>newLine</code>方法演示，代码如下：</p>  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BufferedWriterDemo</span> <span class="title">throws</span> <span class="title">IOException</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException  </span>&#123;</span><br><span class="line">        <span class="comment">// 创建流对象</span></span><br><span class="line">        BufferedWriter bw = <span class="keyword">new</span> BufferedWriter(<span class="keyword">new</span> FileWriter(<span class="string">&quot;out.txt&quot;</span>));</span><br><span class="line">        <span class="comment">// 写出数据</span></span><br><span class="line">        bw.write(<span class="string">&quot;黑马&quot;</span>);</span><br><span class="line">        <span class="comment">// 写出换行</span></span><br><span class="line">        bw.newLine();</span><br><span class="line">        bw.write(<span class="string">&quot;程序&quot;</span>);</span><br><span class="line">        bw.newLine();</span><br><span class="line">        bw.write(<span class="string">&quot;员&quot;</span>);</span><br><span class="line">        bw.newLine();</span><br><span class="line">        <span class="comment">// 释放资源</span></span><br><span class="line">        bw.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出效果:</span><br><span class="line">黑马</span><br><span class="line">程序</span><br><span class="line">员</span><br></pre></td></tr></table></figure><h2 id="1-4-练习-文本排序"><a href="#1-4-练习-文本排序" class="headerlink" title="1.4 练习:文本排序"></a>1.4 练习:文本排序</h2><p>请将文本信息恢复顺序。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">3.侍中、侍郎郭攸之、费祎、董允等，此皆良实，志虑忠纯，是以先帝简拔以遗陛下。愚以为宫中之事，事无大小，悉以咨之，然后施行，必得裨补阙漏，有所广益。</span><br><span class="line">8.愿陛下托臣以讨贼兴复之效，不效，则治臣之罪，以告先帝之灵。若无兴德之言，则责攸之、祎、允等之慢，以彰其咎；陛下亦宜自谋，以咨诹善道，察纳雅言，深追先帝遗诏，臣不胜受恩感激。</span><br><span class="line">4.将军向宠，性行淑均，晓畅军事，试用之于昔日，先帝称之曰能，是以众议举宠为督。愚以为营中之事，悉以咨之，必能使行阵和睦，优劣得所。</span><br><span class="line">2.宫中府中，俱为一体，陟罚臧否，不宜异同。若有作奸犯科及为忠善者，宜付有司论其刑赏，以昭陛下平明之理，不宜偏私，使内外异法也。</span><br><span class="line">1.先帝创业未半而中道崩殂，今天下三分，益州疲弊，此诚危急存亡之秋也。然侍卫之臣不懈于内，忠志之士忘身于外者，盖追先帝之殊遇，欲报之于陛下也。诚宜开张圣听，以光先帝遗德，恢弘志士之气，不宜妄自菲薄，引喻失义，以塞忠谏之路也。</span><br><span class="line">9.今当远离，临表涕零，不知所言。</span><br><span class="line">6.臣本布衣，躬耕于南阳，苟全性命于乱世，不求闻达于诸侯。先帝不以臣卑鄙，猥自枉屈，三顾臣于草庐之中，咨臣以当世之事，由是感激，遂许先帝以驱驰。后值倾覆，受任于败军之际，奉命于危难之间，尔来二十有一年矣。</span><br><span class="line">7.先帝知臣谨慎，故临崩寄臣以大事也。受命以来，夙夜忧叹，恐付托不效，以伤先帝之明，故五月渡泸，深入不毛。今南方已定，兵甲已足，当奖率三军，北定中原，庶竭驽钝，攘除奸凶，兴复汉室，还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益，进尽忠言，则攸之、祎、允之任也。</span><br><span class="line">5.亲贤臣，远小人，此先汉所以兴隆也；亲小人，远贤臣，此后汉所以倾颓也。先帝在时，每与臣论此事，未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军，此悉贞良死节之臣，愿陛下亲之信之，则汉室之隆，可计日而待也。</span><br></pre></td></tr></table></figure><h3 id="案例分析"><a href="#案例分析" class="headerlink" title="案例分析"></a>案例分析</h3><ol><li>逐行读取文本信息。</li><li>解析文本信息到集合中。</li><li>遍历集合，按顺序，写出文本信息。</li></ol><h3 id="案例实现"><a href="#案例实现" class="headerlink" title="案例实现"></a>案例实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BufferedTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 创建map集合,保存文本数据,键为序号,值为文字</span></span><br><span class="line">        HashMap&lt;String, String&gt; lineMap = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 创建流对象</span></span><br><span class="line">        BufferedReader br = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">&quot;in.txt&quot;</span>));</span><br><span class="line">        BufferedWriter bw = <span class="keyword">new</span> BufferedWriter(<span class="keyword">new</span> FileWriter(<span class="string">&quot;out.txt&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 读取数据</span></span><br><span class="line">        String line  = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">while</span> ((line = br.readLine())!=<span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 解析文本</span></span><br><span class="line">            String[] split = line.split(<span class="string">&quot;\\.&quot;</span>);</span><br><span class="line">            <span class="comment">// 保存到集合</span></span><br><span class="line">            lineMap.put(split[<span class="number">0</span>],split[<span class="number">1</span>]);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 释放资源</span></span><br><span class="line">        br.close();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 遍历map集合</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= lineMap.size(); i++) &#123;</span><br><span class="line">            String key = String.valueOf(i);</span><br><span class="line">            <span class="comment">// 获取map中文本</span></span><br><span class="line">            String value = lineMap.get(key);</span><br><span class="line">            <span class="comment">// 写出拼接文本</span></span><br><span class="line">            bw.write(key+<span class="string">&quot;.&quot;</span>+value);</span><br><span class="line">            <span class="comment">// 写出换行</span></span><br><span class="line">            bw.newLine();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 释放资源</span></span><br><span class="line">        bw.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第二章-转换流"><a href="#第二章-转换流" class="headerlink" title="第二章 转换流"></a>第二章 转换流</h1><h2 id="2-1-字符编码和字符集"><a href="#2-1-字符编码和字符集" class="headerlink" title="2.1 字符编码和字符集"></a>2.1 字符编码和字符集</h2><h3 id="字符编码"><a href="#字符编码" class="headerlink" title="字符编码"></a>字符编码</h3><p>计算机中储存的信息都是用二进制数表示的，而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。按照某种规则，将字符存储到计算机中，称为<strong>编码</strong> 。反之，将存储在计算机中的二进制数按照某种规则解析显示出来，称为<strong>解码</strong> 。比如说，按照A规则存储，同样按照A规则解析，那么就能显示正确的文本符号。反之，按照A规则存储，再按照B规则解析，就会导致乱码现象。</p><p>编码:字符(能看懂的)–字节(看不懂的)</p><p>解码:字节(看不懂的)–&gt;字符(能看懂的)</p><ul><li><p><strong>字符编码<code>Character Encoding</code></strong> : 就是一套自然语言的字符与二进制数之间的对应规则。</p><p>编码表:生活中文字和计算机中二进制的对应规则</p></li></ul><h3 id="字符集"><a href="#字符集" class="headerlink" title="字符集"></a>字符集</h3><ul><li>**字符集 <code>Charset</code>**：也叫编码表。是一个系统支持的所有字符的集合，包括各国家文字、标点符号、图形符号、数字等。</li></ul><p>计算机要准确的存储和识别各种字符集符号，需要进行字符编码，一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。<img src= "/img/loading.gif" data-lazy-src="img/1_charset.jpg"></p><p>可见，当指定了<strong>编码</strong>，它所对应的<strong>字符集</strong>自然就指定了，所以<strong>编码</strong>才是我们最终要关心的。</p><ul><li><strong>ASCII字符集</strong> ：<ul><li>ASCII（American Standard Code for Information Interchange，美国信息交换标准代码）是基于拉丁字母的一套电脑编码系统，用于显示现代英语，主要包括控制字符（回车键、退格、换行键等）和可显示字符（英文大小写字符、阿拉伯数字和西文符号）。</li><li>基本的ASCII字符集，使用7位（bits）表示一个字符，共128字符。ASCII的扩展字符集使用8位（bits）表示一个字符，共256字符，方便支持欧洲常用字符。</li></ul></li><li><strong>ISO-8859-1字符集</strong>：<ul><li>拉丁码表，别名Latin-1，用于显示欧洲使用的语言，包括荷兰、丹麦、德语、意大利语、西班牙语等。</li><li>ISO-8859-1使用单字节编码，兼容ASCII编码。</li></ul></li><li><strong>GBxxx字符集</strong>：<ul><li>GB就是国标的意思，是为了显示中文而设计的一套字符集。</li><li><strong>GB2312</strong>：简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时，就表示一个汉字，这样大约可以组合了包含7000多个简体汉字，此外数学符号、罗马希腊的字母、日文的假名们都编进去了，连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码，这就是常说的”全角”字符，而原来在127号以下的那些就叫”半角”字符了。</li><li><strong>GBK</strong>：最常用的中文码表。是在GB2312标准基础上的扩展规范，使用了双字节编码方案，共收录了21003个汉字，完全兼容GB2312标准，同时支持繁体汉字以及日韩汉字等。</li><li><strong>GB18030</strong>：最新的中文码表。收录汉字70244个，采用多字节编码，每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字，同时支持繁体汉字以及日韩汉字等。</li></ul></li><li><strong>Unicode字符集</strong> ：<ul><li>Unicode编码系统为表达任意语言的任意字符而设计，是业界的一种标准，也称为统一码、标准万国码。</li><li>它最多使用4个字节的数字来表达每个字母、符号，或者文字。有三种编码方案，UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。</li><li>UTF-8编码，可以用来表示Unicode标准中任何字符，它是电子邮件、网页及其他存储或传送文字的应用中，优先采用的编码。互联网工程工作小组（IETF）要求所有互联网协议都必须支持UTF-8编码。所以，我们开发Web应用，也要使用UTF-8编码。它使用一至四个字节为每个字符编码，编码规则：<ol><li>128个US-ASCII字符，只需一个字节编码。</li><li>拉丁文等字符，需要二个字节编码。 </li><li>大部分常用字（含中文），使用三个字节编码。</li><li>其他极少使用的Unicode辅助字符，使用四字节编码。</li></ol></li></ul></li></ul><h2 id="2-2-编码引出的问题"><a href="#2-2-编码引出的问题" class="headerlink" title="2.2 编码引出的问题"></a>2.2 编码引出的问题</h2><p>在IDEA中，使用<code>FileReader</code> 读取项目中的文本文件。由于IDEA的设置，都是默认的<code>UTF-8</code>编码，所以没有任何问题。但是，当读取Windows系统中创建的文本文件时，由于Windows系统的默认是GBK编码，就会出现乱码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ReaderDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        FileReader fileReader = <span class="keyword">new</span> FileReader(<span class="string">&quot;E:\\File_GBK.txt&quot;</span>);</span><br><span class="line">        <span class="keyword">int</span> read;</span><br><span class="line">        <span class="keyword">while</span> ((read = fileReader.read()) != -<span class="number">1</span>) &#123;</span><br><span class="line">            System.out.print((<span class="keyword">char</span>)read);</span><br><span class="line">        &#125;</span><br><span class="line">        fileReader.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">���</span><br></pre></td></tr></table></figure><p>那么如何读取GBK编码的文件呢？ </p><h2 id="2-3-InputStreamReader类"><a href="#2-3-InputStreamReader类" class="headerlink" title="2.3 InputStreamReader类"></a>2.3 InputStreamReader类</h2><p>转换流<code>java.io.InputStreamReader</code>，是Reader的子类，是从字节流到字符流的桥梁。它读取字节，并使用指定的字符集将其解码为字符。它的字符集可以由名称指定，也可以接受平台的默认字符集。 </p><h3 id="构造方法-2"><a href="#构造方法-2" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>InputStreamReader(InputStream in)</code>: 创建一个使用默认字符集的字符流。 </li><li><code>InputStreamReader(InputStream in, String charsetName)</code>: 创建一个指定字符集的字符流。</li></ul><p>构造举例，代码如下： </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">InputStreamReader isr = <span class="keyword">new</span> InputStreamReader(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;in.txt&quot;</span>));</span><br><span class="line">InputStreamReader isr2 = <span class="keyword">new</span> InputStreamReader(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;in.txt&quot;</span>) , <span class="string">&quot;GBK&quot;</span>);</span><br></pre></td></tr></table></figure><h3 id="指定编码读取"><a href="#指定编码读取" class="headerlink" title="指定编码读取"></a>指定编码读取</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ReaderDemo2</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 定义文件路径,文件为gbk编码</span></span><br><span class="line">        String FileName = <span class="string">&quot;E:\\file_gbk.txt&quot;</span>;</span><br><span class="line">        <span class="comment">// 创建流对象,默认UTF8编码</span></span><br><span class="line">        InputStreamReader isr = <span class="keyword">new</span> InputStreamReader(<span class="keyword">new</span> FileInputStream(FileName));</span><br><span class="line">        <span class="comment">// 创建流对象,指定GBK编码</span></span><br><span class="line">        InputStreamReader isr2 = <span class="keyword">new</span> InputStreamReader(<span class="keyword">new</span> FileInputStream(FileName) , <span class="string">&quot;GBK&quot;</span>);</span><br><span class="line">        <span class="comment">// 定义变量,保存字符</span></span><br><span class="line">        <span class="keyword">int</span> read;</span><br><span class="line">        <span class="comment">// 使用默认编码字符流读取,乱码</span></span><br><span class="line">        <span class="keyword">while</span> ((read = isr.read()) != -<span class="number">1</span>) &#123;</span><br><span class="line">            System.out.print((<span class="keyword">char</span>)read); <span class="comment">// ��Һ�</span></span><br><span class="line">        &#125;</span><br><span class="line">        isr.close();</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 使用指定编码字符流读取,正常解析</span></span><br><span class="line">        <span class="keyword">while</span> ((read = isr2.read()) != -<span class="number">1</span>) &#123;</span><br><span class="line">            System.out.print((<span class="keyword">char</span>)read);<span class="comment">// 大家好</span></span><br><span class="line">        &#125;</span><br><span class="line">        isr2.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="2-4-OutputStreamWriter类"><a href="#2-4-OutputStreamWriter类" class="headerlink" title="2.4 OutputStreamWriter类"></a>2.4 OutputStreamWriter类</h2><p>转换流<code>java.io.OutputStreamWriter</code> ，是Writer的子类，是从字符流到字节流的桥梁。使用指定的字符集将字符编码为字节。它的字符集可以由名称指定，也可以接受平台的默认字符集。 </p><h3 id="构造方法-3"><a href="#构造方法-3" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>OutputStreamWriter(OutputStream in)</code>: 创建一个使用默认字符集的字符流。 </li><li><code>OutputStreamWriter(OutputStream in, String charsetName)</code>: 创建一个指定字符集的字符流。</li></ul><p>构造举例，代码如下： </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">OutputStreamWriter isr = <span class="keyword">new</span> OutputStreamWriter(<span class="keyword">new</span> FileOutputStream(<span class="string">&quot;out.txt&quot;</span>));</span><br><span class="line">OutputStreamWriter isr2 = <span class="keyword">new</span> OutputStreamWriter(<span class="keyword">new</span> FileOutputStream(<span class="string">&quot;out.txt&quot;</span>) , <span class="string">&quot;GBK&quot;</span>);</span><br></pre></td></tr></table></figure><h3 id="指定编码写出"><a href="#指定编码写出" class="headerlink" title="指定编码写出"></a>指定编码写出</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">OutputDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 定义文件路径</span></span><br><span class="line">        String FileName = <span class="string">&quot;E:\\out.txt&quot;</span>;</span><br><span class="line">        <span class="comment">// 创建流对象,默认UTF8编码</span></span><br><span class="line">        OutputStreamWriter osw = <span class="keyword">new</span> OutputStreamWriter(<span class="keyword">new</span> FileOutputStream(FileName));</span><br><span class="line">        <span class="comment">// 写出数据</span></span><br><span class="line">        osw.write(<span class="string">&quot;你好&quot;</span>); <span class="comment">// 保存为6个字节</span></span><br><span class="line">        osw.close();</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 定义文件路径</span></span><br><span class="line">        String FileName2 = <span class="string">&quot;E:\\out2.txt&quot;</span>;</span><br><span class="line">        <span class="comment">// 创建流对象,指定GBK编码</span></span><br><span class="line">        OutputStreamWriter osw2 = <span class="keyword">new</span> OutputStreamWriter(<span class="keyword">new</span> FileOutputStream(FileName2),<span class="string">&quot;GBK&quot;</span>);</span><br><span class="line">        <span class="comment">// 写出数据</span></span><br><span class="line">        osw2.write(<span class="string">&quot;你好&quot;</span>);<span class="comment">// 保存为4个字节</span></span><br><span class="line">        osw2.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="转换流理解图解"><a href="#转换流理解图解" class="headerlink" title="转换流理解图解"></a>转换流理解图解</h3><p><strong>转换流是字节与字符间的桥梁！</strong><img src= "/img/loading.gif" data-lazy-src="img/2_zhuanhuan.jpg"></p><h2 id="2-5-练习：转换文件编码"><a href="#2-5-练习：转换文件编码" class="headerlink" title="2.5 练习：转换文件编码"></a>2.5 练习：转换文件编码</h2><p>将GBK编码的文本文件，转换为UTF-8编码的文本文件。</p><h3 id="案例分析-1"><a href="#案例分析-1" class="headerlink" title="案例分析"></a>案例分析</h3><ol><li>指定GBK编码的转换流，读取文本文件。</li><li>使用UTF-8编码的转换流，写出文本文件。</li></ol><h3 id="案例实现-1"><a href="#案例实现-1" class="headerlink" title="案例实现"></a>案例实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TransDemo</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;      </span><br><span class="line">        <span class="comment">// 1.定义文件路径</span></span><br><span class="line">        String srcFile = <span class="string">&quot;file_gbk.txt&quot;</span>;</span><br><span class="line">        String destFile = <span class="string">&quot;file_utf8.txt&quot;</span>;</span><br><span class="line">        <span class="comment">// 2.创建流对象</span></span><br><span class="line">        <span class="comment">// 2.1 转换输入流,指定GBK编码</span></span><br><span class="line">        InputStreamReader isr = <span class="keyword">new</span> InputStreamReader(<span class="keyword">new</span> FileInputStream(srcFile) , <span class="string">&quot;GBK&quot;</span>);</span><br><span class="line">        <span class="comment">// 2.2 转换输出流,默认utf8编码</span></span><br><span class="line">        OutputStreamWriter osw = <span class="keyword">new</span> OutputStreamWriter(<span class="keyword">new</span> FileOutputStream(destFile));</span><br><span class="line">        <span class="comment">// 3.读写数据</span></span><br><span class="line">        <span class="comment">// 3.1 定义数组</span></span><br><span class="line">        <span class="keyword">char</span>[] cbuf = <span class="keyword">new</span> <span class="keyword">char</span>[<span class="number">1024</span>];</span><br><span class="line">        <span class="comment">// 3.2 定义长度</span></span><br><span class="line">        <span class="keyword">int</span> len;</span><br><span class="line">        <span class="comment">// 3.3 循环读取</span></span><br><span class="line">        <span class="keyword">while</span> ((len = isr.read(cbuf))!=-<span class="number">1</span>) &#123;</span><br><span class="line">            <span class="comment">// 循环写出</span></span><br><span class="line">            osw.write(cbuf,<span class="number">0</span>,len);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 4.释放资源</span></span><br><span class="line">        osw.close();</span><br><span class="line">        isr.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第三章-序列化"><a href="#第三章-序列化" class="headerlink" title="第三章 序列化"></a>第三章 序列化</h1><h2 id="3-1-概述"><a href="#3-1-概述" class="headerlink" title="3.1 概述"></a>3.1 概述</h2><p>Java 提供了一种对象<strong>序列化</strong>的机制。用一个字节序列可以表示一个对象，该字节序列包含该<code>对象的数据</code>、<code>对象的类型</code>和<code>对象中存储的属性</code>等信息。字节序列写出到文件之后，相当于文件中<strong>持久保存</strong>了一个对象的信息。 </p><p>反之，该字节序列还可以从文件中读取回来，重构对象，对它进行<strong>反序列化</strong>。<code>对象的数据</code>、<code>对象的类型</code>和<code>对象中存储的数据</code>信息，都可以用来在内存中创建对象。看图理解序列化： <img src= "/img/loading.gif" data-lazy-src="img/3_xuliehua.jpg"></p><h2 id="3-2-ObjectOutputStream类"><a href="#3-2-ObjectOutputStream类" class="headerlink" title="3.2 ObjectOutputStream类"></a>3.2 ObjectOutputStream类</h2><p><code>java.io.ObjectOutputStream </code> 类，将Java对象的原始数据类型写出到文件,实现对象的持久存储。</p><h3 id="构造方法-4"><a href="#构造方法-4" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>public ObjectOutputStream(OutputStream out) </code>： 创建一个指定OutputStream的ObjectOutputStream。</li></ul><p>构造举例，代码如下：  </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">FileOutputStream fileOut = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;employee.txt&quot;</span>);</span><br><span class="line">ObjectOutputStream out = <span class="keyword">new</span> ObjectOutputStream(fileOut);</span><br></pre></td></tr></table></figure><h3 id="序列化操作"><a href="#序列化操作" class="headerlink" title="序列化操作"></a>序列化操作</h3><ol><li>一个对象要想序列化，必须满足两个条件:</li></ol><ul><li>该类必须实现<code>java.io.Serializable </code> 接口，<code>Serializable</code> 是一个标记接口，不实现此接口的类将不会使任何状态序列化或反序列化，会抛出<code>NotSerializableException</code> 。</li><li>该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的，则该属性必须注明是瞬态的，使用<code>transient</code> 关键字修饰。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Employee</span> <span class="keyword">implements</span> <span class="title">java</span>.<span class="title">io</span>.<span class="title">Serializable</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> String name;</span><br><span class="line">    <span class="keyword">public</span> String address;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">transient</span> <span class="keyword">int</span> age; <span class="comment">// transient瞬态修饰成员,不会被序列化</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addressCheck</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;Address  check : &quot;</span> + name + <span class="string">&quot; -- &quot;</span> + address);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>2.写出对象方法</p><ul><li><code>public final void writeObject (Object obj)</code> : 将指定的对象写出。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SerializeDemo</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String [] args)</span>   </span>&#123;</span><br><span class="line">        Employee e = <span class="keyword">new</span> Employee();</span><br><span class="line">        e.name = <span class="string">&quot;zhangsan&quot;</span>;</span><br><span class="line">        e.address = <span class="string">&quot;beiqinglu&quot;</span>;</span><br><span class="line">        e.age = <span class="number">20</span>; </span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 创建序列化流对象</span></span><br><span class="line">          ObjectOutputStream out = <span class="keyword">new</span> ObjectOutputStream(<span class="keyword">new</span> FileOutputStream(<span class="string">&quot;employee.txt&quot;</span>));</span><br><span class="line">            <span class="comment">// 写出对象</span></span><br><span class="line">            out.writeObject(e);</span><br><span class="line">            <span class="comment">// 释放资源</span></span><br><span class="line">            out.close();</span><br><span class="line">            fileOut.close();</span><br><span class="line">            System.out.println(<span class="string">&quot;Serialized data is saved&quot;</span>); <span class="comment">// 姓名，地址被序列化，年龄没有被序列化。</span></span><br><span class="line">        &#125; <span class="keyword">catch</span>(IOException i)   &#123;</span><br><span class="line">            i.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">Serialized data is saved</span><br></pre></td></tr></table></figure><h2 id="3-3-ObjectInputStream类"><a href="#3-3-ObjectInputStream类" class="headerlink" title="3.3 ObjectInputStream类"></a>3.3 ObjectInputStream类</h2><p>ObjectInputStream反序列化流，将之前使用ObjectOutputStream序列化的原始数据恢复为对象。 </p><h3 id="构造方法-5"><a href="#构造方法-5" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>public ObjectInputStream(InputStream in) </code>： 创建一个指定InputStream的ObjectInputStream。</li></ul><h3 id="反序列化操作1"><a href="#反序列化操作1" class="headerlink" title="反序列化操作1"></a>反序列化操作1</h3><p>如果能找到一个对象的class文件，我们可以进行反序列化操作，调用<code>ObjectInputStream</code>读取对象的方法：</p><ul><li><code>public final Object readObject ()</code> : 读取一个对象。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DeserializeDemo</span> </span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String [] args)</span>   </span>&#123;</span><br><span class="line">        Employee e = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;       </span><br><span class="line">             <span class="comment">// 创建反序列化流</span></span><br><span class="line">             FileInputStream fileIn = <span class="keyword">new</span> FileInputStream(<span class="string">&quot;employee.txt&quot;</span>);</span><br><span class="line">             ObjectInputStream in = <span class="keyword">new</span> ObjectInputStream(fileIn);</span><br><span class="line">             <span class="comment">// 读取一个对象</span></span><br><span class="line">             e = (Employee) in.readObject();</span><br><span class="line">             <span class="comment">// 释放资源</span></span><br><span class="line">             in.close();</span><br><span class="line">             fileIn.close();</span><br><span class="line">        &#125;<span class="keyword">catch</span>(IOException i) &#123;</span><br><span class="line">             <span class="comment">// 捕获其他异常</span></span><br><span class="line">             i.printStackTrace();</span><br><span class="line">             <span class="keyword">return</span>;</span><br><span class="line">        &#125;<span class="keyword">catch</span>(ClassNotFoundException c)  &#123;</span><br><span class="line">            <span class="comment">// 捕获类找不到异常</span></span><br><span class="line">             System.out.println(<span class="string">&quot;Employee class not found&quot;</span>);</span><br><span class="line">             c.printStackTrace();</span><br><span class="line">             <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 无异常,直接打印输出</span></span><br><span class="line">        System.out.println(<span class="string">&quot;Name: &quot;</span> + e.name);  <span class="comment">// zhangsan</span></span><br><span class="line">        System.out.println(<span class="string">&quot;Address: &quot;</span> + e.address); <span class="comment">// beiqinglu</span></span><br><span class="line">        System.out.println(<span class="string">&quot;age: &quot;</span> + e.age); <span class="comment">// 0</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>对于JVM可以反序列化对象，它必须是能够找到class文件的类。如果找不到该类的class文件，则抛出一个 <code>ClassNotFoundException</code> 异常。</strong>  </p><h3 id="反序列化操作2"><a href="#反序列化操作2" class="headerlink" title="反序列化操作2"></a><strong>反序列化操作2</strong></h3><p><strong>另外，当JVM反序列化对象时，能找到class文件，但是class文件在序列化对象之后发生了修改，那么反序列化操作也会失败，抛出一个<code>InvalidClassException</code>异常。</strong>发生这个异常的原因如下：</p><ul><li>该类的序列版本号与从流中读取的类描述符的版本号不匹配 </li><li>该类包含未知数据类型 </li><li>该类没有可访问的无参数构造方法 </li></ul><p><code>Serializable</code> 接口给需要序列化的类，提供了一个序列版本号。<code>serialVersionUID</code> 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Employee</span> <span class="keyword">implements</span> <span class="title">java</span>.<span class="title">io</span>.<span class="title">Serializable</span> </span>&#123;</span><br><span class="line">     <span class="comment">// 加入序列版本号</span></span><br><span class="line">     <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = <span class="number">1L</span>;</span><br><span class="line">     <span class="keyword">public</span> String name;</span><br><span class="line">     <span class="keyword">public</span> String address;</span><br><span class="line">     <span class="comment">// 添加新的属性 ,重新编译, 可以反序列化,该属性赋为默认值.</span></span><br><span class="line">     <span class="keyword">public</span> <span class="keyword">int</span> eid; </span><br><span class="line"></span><br><span class="line">     <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addressCheck</span><span class="params">()</span> </span>&#123;</span><br><span class="line">         System.out.println(<span class="string">&quot;Address  check : &quot;</span> + name + <span class="string">&quot; -- &quot;</span> + address);</span><br><span class="line">     &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-4-练习：序列化集合"><a href="#3-4-练习：序列化集合" class="headerlink" title="3.4 练习：序列化集合"></a>3.4 练习：序列化集合</h2><ol><li>将存有多个自定义对象的集合序列化操作，保存到<code>list.txt</code>文件中。</li><li>反序列化<code>list.txt</code> ，并遍历集合，打印对象信息。</li></ol><h3 id="案例分析-2"><a href="#案例分析-2" class="headerlink" title="案例分析"></a>案例分析</h3><ol><li>把若干学生对象 ，保存到集合中。</li><li>把集合序列化。</li><li>反序列化读取时，只需要读取一次，转换为集合类型。</li><li>遍历集合，可以打印所有的学生信息</li></ol><h3 id="案例实现-2"><a href="#案例实现-2" class="headerlink" title="案例实现"></a>案例实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SerTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="comment">// 创建 学生对象</span></span><br><span class="line">        Student student = <span class="keyword">new</span> Student(<span class="string">&quot;老王&quot;</span>, <span class="string">&quot;laow&quot;</span>);</span><br><span class="line">        Student student2 = <span class="keyword">new</span> Student(<span class="string">&quot;老张&quot;</span>, <span class="string">&quot;laoz&quot;</span>);</span><br><span class="line">        Student student3 = <span class="keyword">new</span> Student(<span class="string">&quot;老李&quot;</span>, <span class="string">&quot;laol&quot;</span>);</span><br><span class="line"></span><br><span class="line">        ArrayList&lt;Student&gt; arrayList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        arrayList.add(student);</span><br><span class="line">        arrayList.add(student2);</span><br><span class="line">        arrayList.add(student3);</span><br><span class="line">        <span class="comment">// 序列化操作</span></span><br><span class="line">        <span class="comment">// serializ(arrayList);</span></span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 反序列化  </span></span><br><span class="line">        ObjectInputStream ois  = <span class="keyword">new</span> ObjectInputStream(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;list.txt&quot;</span>));</span><br><span class="line">        <span class="comment">// 读取对象,强转为ArrayList类型</span></span><br><span class="line">        ArrayList&lt;Student&gt; list  = (ArrayList&lt;Student&gt;)ois.readObject();</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; list.size(); i++ )&#123;</span><br><span class="line">            Student s = list.get(i);</span><br><span class="line">            System.out.println(s.getName()+<span class="string">&quot;--&quot;</span>+ s.getPwd());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">serializ</span><span class="params">(ArrayList&lt;Student&gt; arrayList)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="comment">// 创建 序列化流 </span></span><br><span class="line">        ObjectOutputStream oos = <span class="keyword">new</span> ObjectOutputStream(<span class="keyword">new</span> FileOutputStream(<span class="string">&quot;list.txt&quot;</span>));</span><br><span class="line">        <span class="comment">// 写出对象</span></span><br><span class="line">        oos.writeObject(arrayList);</span><br><span class="line">        <span class="comment">// 释放资源</span></span><br><span class="line">        oos.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第四章-打印流"><a href="#第四章-打印流" class="headerlink" title="第四章 打印流"></a>第四章 打印流</h1><h2 id="4-1-概述"><a href="#4-1-概述" class="headerlink" title="4.1 概述"></a>4.1 概述</h2><p>平时我们在控制台打印输出，是调用<code>print</code>方法和<code>println</code>方法完成的，这两个方法都来自于<code>java.io.PrintStream</code>类，该类能够方便地打印各种数据类型的值，是一种便捷的输出方式。</p><h2 id="4-2-PrintStream类"><a href="#4-2-PrintStream类" class="headerlink" title="4.2 PrintStream类"></a>4.2 PrintStream类</h2><h3 id="构造方法-6"><a href="#构造方法-6" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>public PrintStream(String fileName)  </code>： 使用指定的文件名创建一个新的打印流。</li></ul><p>构造举例，代码如下：  </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PrintStream ps = <span class="keyword">new</span> PrintStream(<span class="string">&quot;ps.txt&quot;</span>)；</span><br></pre></td></tr></table></figure><h3 id="改变打印流向"><a href="#改变打印流向" class="headerlink" title="改变打印流向"></a>改变打印流向</h3><p><code>System.out</code>就是<code>PrintStream</code>类型的，只不过它的流向是系统规定的，打印在控制台上。不过，既然是流对象，我们就可以玩一个”小把戏”，改变它的流向。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">PrintDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 调用系统的打印流,控制台直接输出97</span></span><br><span class="line">        System.out.println(<span class="number">97</span>);</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 创建打印流,指定文件的名称</span></span><br><span class="line">        PrintStream ps = <span class="keyword">new</span> PrintStream(<span class="string">&quot;ps.txt&quot;</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 设置系统的打印流流向,输出到ps.txt</span></span><br><span class="line">        System.setOut(ps);</span><br><span class="line">        <span class="comment">// 调用系统的打印流,ps.txt中输出97</span></span><br><span class="line">        System.out.println(<span class="number">97</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中字节流、字符流</title>
      <link href="java/javaold/byte/"/>
      <url>java/javaold/byte/</url>
      
        <content type="html"><![CDATA[<h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li>IO流</li><li>字节流</li><li>字符流</li><li>异常处理</li><li>Properties</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><ul><li><input disabled="" type="checkbox"> 能够说出IO流的分类和功能</li><li><input disabled="" type="checkbox"> 能够使用字节输出流写出数据到文件</li><li><input disabled="" type="checkbox"> 能够使用字节输入流读取数据到程序</li><li><input disabled="" type="checkbox"> 能够理解读取数据read(byte[])方法的原理</li><li><input disabled="" type="checkbox"> 能够使用字节流完成文件的复制</li><li><input checked="" disabled="" type="checkbox"> 能够使用FileWirter写数据到文件</li><li><input disabled="" type="checkbox"> 能够说出FileWriter中关闭和刷新方法的区别</li><li><input disabled="" type="checkbox"> 能够使用FileWriter写数据的5个方法</li><li><input disabled="" type="checkbox"> 能够使用FileWriter写数据实现换行和追加写</li><li><input disabled="" type="checkbox"> 能够使用FileReader读数据</li><li><input disabled="" type="checkbox"> 能够使用FileReader读数据一次一个字符数组</li><li><input disabled="" type="checkbox"> 能够使用Properties的load方法加载文件中配置信息</li></ul><h1 id="第一章-IO概述"><a href="#第一章-IO概述" class="headerlink" title="第一章 IO概述"></a>第一章 IO概述</h1><h2 id="1-1-什么是IO"><a href="#1-1-什么是IO" class="headerlink" title="1.1 什么是IO"></a>1.1 什么是IO</h2><p>生活中，你肯定经历过这样的场景。当你编辑一个文本文件，忘记了<code>ctrl+s</code> ，可能文件就白白编辑了。当你电脑上插入一个U盘，可以把一个视频，拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢？键盘、内存、硬盘、外接设备等等。</p><p>我们把这种数据的传输，可以看做是一种数据的流动，按照流动的方向，以内存为基准，分为<code>输入input</code> 和<code>输出output</code> ，即流向内存是输入流，流出内存的输出流。</p><p>Java中I/O操作主要是指使用<code>java.io</code>包下的内容，进行输入、输出操作。<strong>输入</strong>也叫做<strong>读取</strong>数据，<strong>输出</strong>也叫做作<strong>写出</strong>数据。</p><h2 id="1-2-IO的分类"><a href="#1-2-IO的分类" class="headerlink" title="1.2 IO的分类"></a>1.2 IO的分类</h2><p>根据数据的流向分为：<strong>输入流</strong>和<strong>输出流</strong>。</p><ul><li><strong>输入流</strong> ：把数据从<code>其他设备</code>上读取到<code>内存</code>中的流。 </li><li><strong>输出流</strong> ：把数据从<code>内存</code> 中写出到<code>其他设备</code>上的流。</li></ul><p>格局数据的类型分为：<strong>字节流</strong>和<strong>字符流</strong>。</p><ul><li><strong>字节流</strong> ：以字节为单位，读写数据的流。</li><li><strong>字符流</strong> ：以字符为单位，读写数据的流。</li></ul><h2 id="1-3-IO的流向说明图解"><a href="#1-3-IO的流向说明图解" class="headerlink" title="1.3 IO的流向说明图解"></a>1.3 IO的流向说明图解</h2><p><img src= "/img/loading.gif" data-lazy-src="img/1_io.jpg"></p><h2 id="1-4-顶级父类们"><a href="#1-4-顶级父类们" class="headerlink" title="1.4 顶级父类们"></a>1.4 顶级父类们</h2><table><thead><tr><th align="center"></th><th align="center"><strong>输入流</strong></th><th align="center">输出流</th></tr></thead><tbody><tr><td align="center"><strong>字节流</strong></td><td align="center">字节输入流<br /><strong>InputStream</strong></td><td align="center">字节输出流<br /><strong>OutputStream</strong></td></tr><tr><td align="center"><strong>字符流</strong></td><td align="center">字符输入流<br /><strong>Reader</strong></td><td align="center">字符输出流<br /><strong>Writer</strong></td></tr></tbody></table><h1 id="第二章-字节流"><a href="#第二章-字节流" class="headerlink" title="第二章 字节流"></a>第二章 字节流</h1><h2 id="2-1-一切皆为字节"><a href="#2-1-一切皆为字节" class="headerlink" title="2.1 一切皆为字节"></a>2.1 一切皆为字节</h2><p>一切文件数据(文本、图片、视频等)在存储时，都是以二进制数字的形式保存，都一个一个的字节，那么传输时一样如此。所以，字节流可以传输任意文件数据。在操作流的时候，我们要时刻明确，无论使用什么样的流对象，底层传输的始终为二进制数据。</p><h2 id="2-2-字节输出流【OutputStream】"><a href="#2-2-字节输出流【OutputStream】" class="headerlink" title="2.2 字节输出流【OutputStream】"></a>2.2 字节输出流【OutputStream】</h2><p><code>java.io.OutputStream </code>抽象类是表示字节输出流的所有类的超类，将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。</p><ul><li><code>public void close()</code> ：关闭此输出流并释放与此流相关联的任何系统资源。  </li><li><code>public void flush() </code> ：刷新此输出流并强制任何缓冲的输出字节被写出。  </li><li><code>public void write(byte[] b)</code>：将 b.length字节从指定的字节数组写入此输出流。  </li><li><code>public void write(byte[] b, int off, int len)</code> ：从指定的字节数组写入 len字节，从偏移量 off开始输出到此输出流。  </li><li><code>public abstract void write(int b)</code> ：将指定的字节输出流。</li></ul><blockquote><p>小贴士：</p><p>close方法，当完成流的操作时，必须调用此方法，释放系统资源。</p></blockquote><h2 id="2-3-FileOutputStream类"><a href="#2-3-FileOutputStream类" class="headerlink" title="2.3 FileOutputStream类"></a>2.3 FileOutputStream类</h2><p><code>OutputStream</code>有很多子类，我们从最简单的一个子类开始。</p><p><code>java.io.FileOutputStream </code>类是文件输出流，用于将数据写出到文件。</p><h3 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>public FileOutputStream(File file)</code>：创建文件输出流以写入由指定的 File对象表示的文件。 </li><li><code>public FileOutputStream(String name)</code>： 创建文件输出流以指定的名称写入文件。  </li></ul><p>当你创建一个流对象时，必须传入一个文件路径。该路径下，如果没有这个文件，会创建该文件。如果有这个文件，会清空这个文件的数据。</p><ul><li>构造举例，代码如下：</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileOutputStreamConstructor</span> <span class="title">throws</span> <span class="title">IOException</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">      <span class="comment">// 使用File对象创建流对象</span></span><br><span class="line">        File file = <span class="keyword">new</span> File(<span class="string">&quot;a.txt&quot;</span>);</span><br><span class="line">        FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(file);</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;b.txt&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="写出字节数据"><a href="#写出字节数据" class="headerlink" title="写出字节数据"></a>写出字节数据</h3><ol><li><strong>写出字节</strong>：<code>write(int b)</code> 方法，每次可以写出一个字节数据，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FOSWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;fos.txt&quot;</span>);     </span><br><span class="line">        <span class="comment">// 写出数据</span></span><br><span class="line">        fos.write(<span class="number">97</span>); <span class="comment">// 写出第1个字节</span></span><br><span class="line">        fos.write(<span class="number">98</span>); <span class="comment">// 写出第2个字节</span></span><br><span class="line">        fos.write(<span class="number">99</span>); <span class="comment">// 写出第3个字节</span></span><br><span class="line">        <span class="comment">// 关闭资源</span></span><br><span class="line">        fos.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">abc</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：</p><ol><li>虽然参数为int类型四个字节，但是只会保留一个字节的信息写出。</li><li>流操作完毕后，必须释放系统资源，调用close方法，千万记得。</li></ol></blockquote><ol start="2"><li><strong>写出字节数组</strong>：<code>write(byte[] b)</code>，每次可以写出数组中的数据，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FOSWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;fos.txt&quot;</span>);     </span><br><span class="line">        <span class="comment">// 字符串转换为字节数组</span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="string">&quot;黑马程序员&quot;</span>.getBytes();</span><br><span class="line">        <span class="comment">// 写出字节数组数据</span></span><br><span class="line">        fos.write(b);</span><br><span class="line">        <span class="comment">// 关闭资源</span></span><br><span class="line">        fos.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">黑马程序员</span><br></pre></td></tr></table></figure><ol start="3"><li><strong>写出指定长度字节数组</strong>：<code>write(byte[] b, int off, int len)</code> ,每次写出从off索引开始，len个字节，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FOSWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;fos.txt&quot;</span>);     </span><br><span class="line">        <span class="comment">// 字符串转换为字节数组</span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="string">&quot;abcde&quot;</span>.getBytes();</span><br><span class="line">    <span class="comment">// 写出从索引2开始，2个字节。索引2是c，两个字节，也就是cd。</span></span><br><span class="line">        fos.write(b,<span class="number">2</span>,<span class="number">2</span>);</span><br><span class="line">        <span class="comment">// 关闭资源</span></span><br><span class="line">        fos.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">cd</span><br></pre></td></tr></table></figure><h3 id="数据追加续写"><a href="#数据追加续写" class="headerlink" title="数据追加续写"></a>数据追加续写</h3><p>经过以上的演示，每次程序运行，创建输出流对象，都会清空目标文件中的数据。如何保留目标文件中数据，还能继续添加新数据呢？</p><ul><li><code>public FileOutputStream(File file, boolean append)</code>： 创建文件输出流以写入由指定的 File对象表示的文件。  </li><li><code>public FileOutputStream(String name, boolean append)</code>： 创建文件输出流以指定的名称写入文件。  </li></ul><p>这两个构造方法，参数中都需要传入一个boolean类型的值，<code>true</code> 表示追加数据，<code>false</code> 表示清空原有数据。这样创建的输出流对象，就可以指定是否追加续写了，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FOSWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;fos.txt&quot;</span>，<span class="keyword">true</span>);     </span><br><span class="line">        <span class="comment">// 字符串转换为字节数组</span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="string">&quot;abcde&quot;</span>.getBytes();</span><br><span class="line">    <span class="comment">// 写出从索引2开始，2个字节。索引2是c，两个字节，也就是cd。</span></span><br><span class="line">        fos.write(b);</span><br><span class="line">        <span class="comment">// 关闭资源</span></span><br><span class="line">        fos.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">文件操作前：cd</span><br><span class="line">文件操作后：cdabcde</span><br></pre></td></tr></table></figure><h3 id="写出换行"><a href="#写出换行" class="headerlink" title="写出换行"></a>写出换行</h3><p>Windows系统里，换行符号是<code>\r\n</code> 。把</p><p>以指定是否追加续写了，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FOSWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;fos.txt&quot;</span>);  </span><br><span class="line">        <span class="comment">// 定义字节数组</span></span><br><span class="line">        <span class="keyword">byte</span>[] words = &#123;<span class="number">97</span>,<span class="number">98</span>,<span class="number">99</span>,<span class="number">100</span>,<span class="number">101</span>&#125;;</span><br><span class="line">        <span class="comment">// 遍历数组</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; words.length; i++) &#123;</span><br><span class="line">            <span class="comment">// 写出一个字节</span></span><br><span class="line">            fos.write(words[i]);</span><br><span class="line">            <span class="comment">// 写出一个换行, 换行符号转成数组写出</span></span><br><span class="line">            fos.write(<span class="string">&quot;\r\n&quot;</span>.getBytes());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 关闭资源</span></span><br><span class="line">        fos.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">输出结果：</span><br><span class="line">a</span><br><span class="line">b</span><br><span class="line">c</span><br><span class="line">d</span><br><span class="line">e</span><br></pre></td></tr></table></figure><blockquote><ul><li>回车符<code>\r</code>和换行符<code>\n</code> ：<ul><li>回车符：回到一行的开头（return）。</li><li>换行符：下一行（newline）。</li></ul></li><li>系统中的换行：<ul><li>Windows系统里，每行结尾是 <code>回车+换行</code> ，即<code>\r\n</code>；</li><li>Unix系统里，每行结尾只有 <code>换行</code> ，即<code>\n</code>；</li><li>Mac系统里，每行结尾是 <code>回车</code> ，即<code>\r</code>。从 Mac OS X开始与Linux统一。</li></ul></li></ul></blockquote><h2 id="2-4-字节输入流【InputStream】"><a href="#2-4-字节输入流【InputStream】" class="headerlink" title="2.4 字节输入流【InputStream】"></a>2.4 字节输入流【InputStream】</h2><p><code>java.io.InputStream </code>抽象类是表示字节输入流的所有类的超类，可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。</p><ul><li><code>public void close()</code> ：关闭此输入流并释放与此流相关联的任何系统资源。    </li><li><code>public abstract int read()</code>： 从输入流读取数据的下一个字节。 </li><li><code>public int read(byte[] b)</code>： 从输入流中读取一些字节数，并将它们存储到字节数组 b中 。</li></ul><blockquote><p>小贴士：</p><p>close方法，当完成流的操作时，必须调用此方法，释放系统资源。</p></blockquote><h2 id="2-5-FileInputStream类"><a href="#2-5-FileInputStream类" class="headerlink" title="2.5 FileInputStream类"></a>2.5 FileInputStream类</h2><p><code>java.io.FileInputStream </code>类是文件输入流，从文件中读取字节。</p><h3 id="构造方法-1"><a href="#构造方法-1" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>FileInputStream(File file)</code>： 通过打开与实际文件的连接来创建一个 FileInputStream ，该文件由文件系统中的 File对象 file命名。 </li><li><code>FileInputStream(String name)</code>： 通过打开与实际文件的连接来创建一个 FileInputStream ，该文件由文件系统中的路径名 name命名。  </li></ul><p>当你创建一个流对象时，必须传入一个文件路径。该路径下，如果没有该文件,会抛出<code>FileNotFoundException</code> 。</p><ul><li>构造举例，代码如下：</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileInputStreamConstructor</span> <span class="title">throws</span> <span class="title">IOException</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">      <span class="comment">// 使用File对象创建流对象</span></span><br><span class="line">        File file = <span class="keyword">new</span> File(<span class="string">&quot;a.txt&quot;</span>);</span><br><span class="line">        FileInputStream fos = <span class="keyword">new</span> FileInputStream(file);</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileInputStream fos = <span class="keyword">new</span> FileInputStream(<span class="string">&quot;b.txt&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="读取字节数据"><a href="#读取字节数据" class="headerlink" title="读取字节数据"></a>读取字节数据</h3><ol><li><strong>读取字节</strong>：<code>read</code>方法，每次可以读取一个字节的数据，提升为int类型，读取到文件末尾，返回<code>-1</code>，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FISRead</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException</span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileInputStream fis = <span class="keyword">new</span> FileInputStream(<span class="string">&quot;read.txt&quot;</span>);</span><br><span class="line">        <span class="comment">// 读取数据，返回一个字节</span></span><br><span class="line">        <span class="keyword">int</span> read = fis.read();</span><br><span class="line">        System.out.println((<span class="keyword">char</span>) read);</span><br><span class="line">        read = fis.read();</span><br><span class="line">        System.out.println((<span class="keyword">char</span>) read);</span><br><span class="line">        read = fis.read();</span><br><span class="line">        System.out.println((<span class="keyword">char</span>) read);</span><br><span class="line">        read = fis.read();</span><br><span class="line">        System.out.println((<span class="keyword">char</span>) read);</span><br><span class="line">        read = fis.read();</span><br><span class="line">        System.out.println((<span class="keyword">char</span>) read);</span><br><span class="line">        <span class="comment">// 读取到末尾,返回-1</span></span><br><span class="line">        read = fis.read();</span><br><span class="line">        System.out.println( read);</span><br><span class="line">    <span class="comment">// 关闭资源</span></span><br><span class="line">        fis.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">a</span><br><span class="line">b</span><br><span class="line">c</span><br><span class="line">d</span><br><span class="line">e</span><br><span class="line">-<span class="number">1</span></span><br></pre></td></tr></table></figure><p>循环改进读取方式，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FISRead</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException</span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileInputStream fis = <span class="keyword">new</span> FileInputStream(<span class="string">&quot;read.txt&quot;</span>);</span><br><span class="line">        <span class="comment">// 定义变量，保存数据</span></span><br><span class="line">        <span class="keyword">int</span> b ；</span><br><span class="line">        <span class="comment">// 循环读取</span></span><br><span class="line">        <span class="keyword">while</span> ((b = fis.read())!=-<span class="number">1</span>) &#123;</span><br><span class="line">            System.out.println((<span class="keyword">char</span>)b);</span><br><span class="line">        &#125;</span><br><span class="line">    <span class="comment">// 关闭资源</span></span><br><span class="line">        fis.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">a</span><br><span class="line">b</span><br><span class="line">c</span><br><span class="line">d</span><br><span class="line">e</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：</p><ol><li>虽然读取了一个字节，但是会自动提升为int类型。</li><li>流操作完毕后，必须释放系统资源，调用close方法，千万记得。</li></ol></blockquote><ol start="2"><li><strong>使用字节数组读取</strong>：<code>read(byte[] b)</code>，每次读取b的长度个字节到数组中，返回读取到的有效字节个数，读取到末尾时，返回<code>-1</code> ，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FISRead</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException</span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象.</span></span><br><span class="line">        FileInputStream fis = <span class="keyword">new</span> FileInputStream(<span class="string">&quot;read.txt&quot;</span>); <span class="comment">// 文件中为abcde</span></span><br><span class="line">        <span class="comment">// 定义变量，作为有效个数</span></span><br><span class="line">        <span class="keyword">int</span> len ；</span><br><span class="line">        <span class="comment">// 定义字节数组，作为装字节数据的容器   </span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">2</span>];</span><br><span class="line">        <span class="comment">// 循环读取</span></span><br><span class="line">        <span class="keyword">while</span> (( len= fis.read(b))!=-<span class="number">1</span>) &#123;</span><br><span class="line">            <span class="comment">// 每次读取后,把数组变成字符串打印</span></span><br><span class="line">            System.out.println(<span class="keyword">new</span> String(b));</span><br><span class="line">        &#125;</span><br><span class="line">    <span class="comment">// 关闭资源</span></span><br><span class="line">        fis.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">输出结果：</span><br><span class="line">ab</span><br><span class="line">cd</span><br><span class="line">ed</span><br></pre></td></tr></table></figure><p>错误数据<code>d</code>，是由于最后一次读取时，只读取一个字节<code>e</code>，数组中，上次读取的数据没有被完全替换，所以要通过<code>len</code> ，获取有效的字节，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FISRead</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException</span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象.</span></span><br><span class="line">        FileInputStream fis = <span class="keyword">new</span> FileInputStream(<span class="string">&quot;read.txt&quot;</span>); <span class="comment">// 文件中为abcde</span></span><br><span class="line">        <span class="comment">// 定义变量，作为有效个数</span></span><br><span class="line">        <span class="keyword">int</span> len ；</span><br><span class="line">        <span class="comment">// 定义字节数组，作为装字节数据的容器   </span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">2</span>];</span><br><span class="line">        <span class="comment">// 循环读取</span></span><br><span class="line">        <span class="keyword">while</span> (( len= fis.read(b))!=-<span class="number">1</span>) &#123;</span><br><span class="line">            <span class="comment">// 每次读取后,把数组的有效字节部分，变成字符串打印</span></span><br><span class="line">            System.out.println(<span class="keyword">new</span> String(b，<span class="number">0</span>，len));<span class="comment">//  len 每次读取的有效字节个数</span></span><br><span class="line">        &#125;</span><br><span class="line">    <span class="comment">// 关闭资源</span></span><br><span class="line">        fis.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">输出结果：</span><br><span class="line">ab</span><br><span class="line">cd</span><br><span class="line">e</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：</p><p>使用数组读取，每次读取多个字节，减少了系统间的IO操作次数，从而提高了读写的效率，建议开发中使用。</p></blockquote><h2 id="2-6-字节流练习：图片复制"><a href="#2-6-字节流练习：图片复制" class="headerlink" title="2.6 字节流练习：图片复制"></a>2.6 字节流练习：图片复制</h2><h3 id="复制原理图解"><a href="#复制原理图解" class="headerlink" title="复制原理图解"></a>复制原理图解</h3><p><img src= "/img/loading.gif" data-lazy-src="img/2_copy.jpg"></p><h3 id="案例实现"><a href="#案例实现" class="headerlink" title="案例实现"></a>案例实现</h3><p>复制图片文件，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Copy</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 1.创建流对象</span></span><br><span class="line">        <span class="comment">// 1.1 指定数据源</span></span><br><span class="line">        FileInputStream fis = <span class="keyword">new</span> FileInputStream(<span class="string">&quot;D:\\test.jpg&quot;</span>);</span><br><span class="line">        <span class="comment">// 1.2 指定目的地</span></span><br><span class="line">        FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;test_copy.jpg&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 2.读写数据</span></span><br><span class="line">        <span class="comment">// 2.1 定义数组</span></span><br><span class="line">        <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>];</span><br><span class="line">        <span class="comment">// 2.2 定义长度</span></span><br><span class="line">        <span class="keyword">int</span> len;</span><br><span class="line">        <span class="comment">// 2.3 循环读取</span></span><br><span class="line">        <span class="keyword">while</span> ((len = fis.read(b))!=-<span class="number">1</span>) &#123;</span><br><span class="line">            <span class="comment">// 2.4 写出数据</span></span><br><span class="line">            fos.write(b, <span class="number">0</span> , len);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3.关闭资源</span></span><br><span class="line">        fos.close();</span><br><span class="line">        fis.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：</p><p>流的关闭原则：先开后关，后开先关。</p></blockquote><h1 id="第三章-字符流"><a href="#第三章-字符流" class="headerlink" title="第三章 字符流"></a>第三章 字符流</h1><p>当使用字节流读取文本文件时，可能会有一个小问题。就是遇到中文字符时，可能不会显示完整的字符，那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类，以字符为单位读写数据，专门用于处理文本文件。</p><h2 id="3-1-字符输入流【Reader】"><a href="#3-1-字符输入流【Reader】" class="headerlink" title="3.1 字符输入流【Reader】"></a>3.1 字符输入流【Reader】</h2><p><code>java.io.Reader</code>抽象类是表示用于读取字符流的所有类的超类，可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。</p><ul><li><code>public void close()</code> ：关闭此流并释放与此流相关联的任何系统资源。    </li><li><code>public int read()</code>： 从输入流读取一个字符。 </li><li><code>public int read(char[] cbuf)</code>： 从输入流中读取一些字符，并将它们存储到字符数组 cbuf中 。</li></ul><h2 id="3-2-FileReader类"><a href="#3-2-FileReader类" class="headerlink" title="3.2 FileReader类"></a>3.2 FileReader类</h2><p><code>java.io.FileReader </code>类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。</p><blockquote><p>小贴士：</p><ol><li><p>字符编码：字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。</p><p>idea中UTF-8</p></li><li><p>字节缓冲区：一个字节数组，用来临时存储字节数据。</p></li></ol></blockquote><h3 id="构造方法-2"><a href="#构造方法-2" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>FileReader(File file)</code>： 创建一个新的 FileReader ，给定要读取的File对象。   </li><li><code>FileReader(String fileName)</code>： 创建一个新的 FileReader ，给定要读取的文件的名称。  </li></ul><p>当你创建一个流对象时，必须传入一个文件路径。类似于FileInputStream 。</p><ul><li>构造举例，代码如下：</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileReaderConstructor</span> <span class="title">throws</span> <span class="title">IOException</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">      <span class="comment">// 使用File对象创建流对象</span></span><br><span class="line">        File file = <span class="keyword">new</span> File(<span class="string">&quot;a.txt&quot;</span>);</span><br><span class="line">        FileReader fr = <span class="keyword">new</span> FileReader(file);</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileReader fr = <span class="keyword">new</span> FileReader(<span class="string">&quot;b.txt&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="读取字符数据"><a href="#读取字符数据" class="headerlink" title="读取字符数据"></a>读取字符数据</h3><ol><li><strong>读取字符</strong>：<code>read</code>方法，每次可以读取一个字符的数据，提升为int类型，读取到文件末尾，返回<code>-1</code>，循环读取，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FRRead</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileReader fr = <span class="keyword">new</span> FileReader(<span class="string">&quot;read.txt&quot;</span>);</span><br><span class="line">        <span class="comment">// 定义变量，保存数据</span></span><br><span class="line">        <span class="keyword">int</span> b ；</span><br><span class="line">        <span class="comment">// 循环读取</span></span><br><span class="line">        <span class="keyword">while</span> ((b = fr.read())!=-<span class="number">1</span>) &#123;</span><br><span class="line">            System.out.println((<span class="keyword">char</span>)b);</span><br><span class="line">        &#125;</span><br><span class="line">    <span class="comment">// 关闭资源</span></span><br><span class="line">        fr.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">黑</span><br><span class="line">马</span><br><span class="line">程</span><br><span class="line">序</span><br><span class="line">员</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：虽然读取了一个字符，但是会自动提升为int类型。</p></blockquote><ol start="2"><li><strong>使用字符数组读取</strong>：<code>read(char[] cbuf)</code>，每次读取b的长度个字符到数组中，返回读取到的有效字符个数，读取到末尾时，返回<code>-1</code> ，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FRRead</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileReader fr = <span class="keyword">new</span> FileReader(<span class="string">&quot;read.txt&quot;</span>);</span><br><span class="line">        <span class="comment">// 定义变量，保存有效字符个数</span></span><br><span class="line">        <span class="keyword">int</span> len ；</span><br><span class="line">        <span class="comment">// 定义字符数组，作为装字符数据的容器</span></span><br><span class="line">         <span class="keyword">char</span>[] cbuf = <span class="keyword">new</span> <span class="keyword">char</span>[<span class="number">2</span>];</span><br><span class="line">        <span class="comment">// 循环读取</span></span><br><span class="line">        <span class="keyword">while</span> ((len = fr.read(cbuf))!=-<span class="number">1</span>) &#123;</span><br><span class="line">            System.out.println(<span class="keyword">new</span> String(cbuf));</span><br><span class="line">        &#125;</span><br><span class="line">    <span class="comment">// 关闭资源</span></span><br><span class="line">        fr.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">黑马</span><br><span class="line">程序</span><br><span class="line">员序</span><br></pre></td></tr></table></figure><p>获取有效的字符改进，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FISRead</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileReader fr = <span class="keyword">new</span> FileReader(<span class="string">&quot;read.txt&quot;</span>);</span><br><span class="line">        <span class="comment">// 定义变量，保存有效字符个数</span></span><br><span class="line">        <span class="keyword">int</span> len ；</span><br><span class="line">        <span class="comment">// 定义字符数组，作为装字符数据的容器</span></span><br><span class="line">        <span class="keyword">char</span>[] cbuf = <span class="keyword">new</span> <span class="keyword">char</span>[<span class="number">2</span>];</span><br><span class="line">        <span class="comment">// 循环读取</span></span><br><span class="line">        <span class="keyword">while</span> ((len = fr.read(cbuf))!=-<span class="number">1</span>) &#123;</span><br><span class="line">            System.out.println(<span class="keyword">new</span> String(cbuf,<span class="number">0</span>,len));</span><br><span class="line">        &#125;</span><br><span class="line">      <span class="comment">// 关闭资源</span></span><br><span class="line">        fr.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">输出结果：</span><br><span class="line">黑马</span><br><span class="line">程序</span><br><span class="line">员</span><br></pre></td></tr></table></figure><h2 id="3-3-字符输出流【Writer】"><a href="#3-3-字符输出流【Writer】" class="headerlink" title="3.3 字符输出流【Writer】"></a>3.3 字符输出流【Writer】</h2><p><code>java.io.Writer </code>抽象类是表示用于写出字符流的所有类的超类，将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。</p><ul><li><code>void write(int c)</code> 写入单个字符。</li><li><code>void write(char[] cbuf) </code>写入字符数组。 </li><li><code>abstract  void write(char[] cbuf, int off, int len) </code>写入字符数组的某一部分,off数组的开始索引,len写的字符个数。 </li><li><code>void write(String str) </code>写入字符串。 </li><li><code>void write(String str, int off, int len)</code> 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。</li><li><code>void flush() </code>刷新该流的缓冲。  </li><li><code>void close()</code> 关闭此流，但要先刷新它。 </li></ul><h2 id="3-4-FileWriter类"><a href="#3-4-FileWriter类" class="headerlink" title="3.4 FileWriter类"></a>3.4 FileWriter类</h2><p><code>java.io.FileWriter </code>类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。</p><h3 id="构造方法-3"><a href="#构造方法-3" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>FileWriter(File file)</code>： 创建一个新的 FileWriter，给定要读取的File对象。   </li><li><code>FileWriter(String fileName)</code>： 创建一个新的 FileWriter，给定要读取的文件的名称。  </li></ul><p>当你创建一个流对象时，必须传入一个文件路径，类似于FileOutputStream。</p><ul><li>构造举例，代码如下：</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileWriterConstructor</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">      <span class="comment">// 使用File对象创建流对象</span></span><br><span class="line">        File file = <span class="keyword">new</span> File(<span class="string">&quot;a.txt&quot;</span>);</span><br><span class="line">        FileWriter fw = <span class="keyword">new</span> FileWriter(file);</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileWriter fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;b.txt&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="基本写出数据"><a href="#基本写出数据" class="headerlink" title="基本写出数据"></a>基本写出数据</h3><p><strong>写出字符</strong>：<code>write(int b)</code> 方法，每次可以写出一个字符数据，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FWWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileWriter fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;fw.txt&quot;</span>);     </span><br><span class="line">        <span class="comment">// 写出数据</span></span><br><span class="line">        fw.write(<span class="number">97</span>); <span class="comment">// 写出第1个字符</span></span><br><span class="line">        fw.write(<span class="string">&#x27;b&#x27;</span>); <span class="comment">// 写出第2个字符</span></span><br><span class="line">        fw.write(<span class="string">&#x27;C&#x27;</span>); <span class="comment">// 写出第3个字符</span></span><br><span class="line">        fw.write(<span class="number">30000</span>); <span class="comment">// 写出第4个字符，中文编码表中30000对应一个汉字。</span></span><br><span class="line">      </span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">        【注意】关闭资源时,与FileOutputStream不同。</span></span><br><span class="line"><span class="comment">         如果不关闭,数据只是保存到缓冲区，并未保存到文件。</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line">        <span class="comment">// fw.close();</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">abC田</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：</p><ol><li>虽然参数为int类型四个字节，但是只会保留一个字符的信息写出。</li><li>未调用close方法，数据只是保存到了缓冲区，并未写出到文件中。</li></ol></blockquote><h3 id="关闭和刷新"><a href="#关闭和刷新" class="headerlink" title="关闭和刷新"></a>关闭和刷新</h3><p>因为内置缓冲区的原因，如果不关闭输出流，无法写出字符到文件中。但是关闭的流对象，是无法继续写出数据的。如果我们既想写出数据，又想继续使用流，就需要<code>flush</code> 方法了。</p><ul><li><code>flush</code> ：刷新缓冲区，流对象可以继续使用。</li><li><code>close </code>:先刷新缓冲区，然后通知系统释放资源。流对象不可以再被使用了。</li></ul><p>代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FWWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileWriter fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;fw.txt&quot;</span>);</span><br><span class="line">        <span class="comment">// 写出数据，通过flush</span></span><br><span class="line">        fw.write(<span class="string">&#x27;刷&#x27;</span>); <span class="comment">// 写出第1个字符</span></span><br><span class="line">        fw.flush();</span><br><span class="line">        fw.write(<span class="string">&#x27;新&#x27;</span>); <span class="comment">// 继续写出第2个字符，写出成功</span></span><br><span class="line">        fw.flush();</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 写出数据，通过close</span></span><br><span class="line">        fw.write(<span class="string">&#x27;关&#x27;</span>); <span class="comment">// 写出第1个字符</span></span><br><span class="line">        fw.close();</span><br><span class="line">        fw.write(<span class="string">&#x27;闭&#x27;</span>); <span class="comment">// 继续写出第2个字符,【报错】java.io.IOException: Stream closed</span></span><br><span class="line">        fw.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：即便是flush方法写出了数据，操作的最后还是要调用close方法，释放系统资源。</p></blockquote><h3 id="写出其他数据"><a href="#写出其他数据" class="headerlink" title="写出其他数据"></a>写出其他数据</h3><ol><li><strong>写出字符数组</strong> ：<code>write(char[] cbuf)</code> 和 <code>write(char[] cbuf, int off, int len)</code> ，每次可以写出字符数组中的数据，用法类似FileOutputStream，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FWWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileWriter fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;fw.txt&quot;</span>);     </span><br><span class="line">        <span class="comment">// 字符串转换为字节数组</span></span><br><span class="line">        <span class="keyword">char</span>[] chars = <span class="string">&quot;黑马程序员&quot;</span>.toCharArray();</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 写出字符数组</span></span><br><span class="line">        fw.write(chars); <span class="comment">// 黑马程序员</span></span><br><span class="line">        </span><br><span class="line">    <span class="comment">// 写出从索引2开始，2个字节。索引2是&#x27;程&#x27;，两个字节，也就是&#x27;程序&#x27;。</span></span><br><span class="line">        fw.write(b,<span class="number">2</span>,<span class="number">2</span>); <span class="comment">// 程序</span></span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 关闭资源</span></span><br><span class="line">        fos.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li><strong>写出字符串</strong>：<code>write(String str)</code> 和 <code>write(String str, int off, int len)</code> ，每次可以写出字符串中的数据，更为方便，代码使用演示：</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FWWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象</span></span><br><span class="line">        FileWriter fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;fw.txt&quot;</span>);     </span><br><span class="line">        <span class="comment">// 字符串</span></span><br><span class="line">        String msg = <span class="string">&quot;黑马程序员&quot;</span>;</span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 写出字符数组</span></span><br><span class="line">        fw.write(msg); <span class="comment">//黑马程序员</span></span><br><span class="line">      </span><br><span class="line">    <span class="comment">// 写出从索引2开始，2个字节。索引2是&#x27;程&#x27;，两个字节，也就是&#x27;程序&#x27;。</span></span><br><span class="line">        fw.write(msg,<span class="number">2</span>,<span class="number">2</span>);  <span class="comment">// 程序</span></span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 关闭资源</span></span><br><span class="line">        fos.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="3"><li><strong>续写和换行</strong>：操作类似于FileOutputStream。</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FWWrite</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 使用文件名称创建流对象，可以续写数据</span></span><br><span class="line">        FileWriter fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;fw.txt&quot;</span>，<span class="keyword">true</span>);     </span><br><span class="line">        <span class="comment">// 写出字符串</span></span><br><span class="line">        fw.write(<span class="string">&quot;黑马&quot;</span>);</span><br><span class="line">        <span class="comment">// 写出换行</span></span><br><span class="line">        fw.write(<span class="string">&quot;\r\n&quot;</span>);</span><br><span class="line">        <span class="comment">// 写出字符串</span></span><br><span class="line">      fw.write(<span class="string">&quot;程序员&quot;</span>);</span><br><span class="line">        <span class="comment">// 关闭资源</span></span><br><span class="line">        fw.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果:</span><br><span class="line">黑马</span><br><span class="line">程序员</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：字符流，只能操作文本文件，不能操作图片，视频等非文本文件。</p><p>当我们单纯读或者写文本文件时  使用字符流 其他情况使用字节流</p></blockquote><h1 id="第四章-IO异常的处理"><a href="#第四章-IO异常的处理" class="headerlink" title="第四章 IO异常的处理"></a>第四章 IO异常的处理</h1><h3 id="JDK7前处理"><a href="#JDK7前处理" class="headerlink" title="JDK7前处理"></a>JDK7前处理</h3><p>之前的入门练习，我们一直把异常抛出，而实际开发中并不能这样处理，建议使用<code>try...catch...finally</code> 代码块，处理异常部分，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HandleException1</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 声明变量</span></span><br><span class="line">        FileWriter fw = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//创建流对象</span></span><br><span class="line">            fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;fw.txt&quot;</span>);</span><br><span class="line">            <span class="comment">// 写出数据</span></span><br><span class="line">            fw.write(<span class="string">&quot;黑马程序员&quot;</span>); <span class="comment">//黑马程序员</span></span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (fw != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    fw.close();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="JDK7的处理-扩展知识点了解内容"><a href="#JDK7的处理-扩展知识点了解内容" class="headerlink" title="JDK7的处理(扩展知识点了解内容)"></a>JDK7的处理(扩展知识点了解内容)</h3><p>还可以使用JDK7优化后的<code>try-with-resource</code> 语句，该语句确保了每个资源在语句结束时关闭。所谓的资源（resource）是指在程序完成后，必须关闭的对象。</p><p>格式：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> (创建流对象语句，如果多个,使用<span class="string">&#x27;;&#x27;</span>隔开) &#123;</span><br><span class="line">  <span class="comment">// 读写数据</span></span><br><span class="line">&#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">  e.printStackTrace();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HandleException2</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建流对象</span></span><br><span class="line">        <span class="keyword">try</span> ( FileWriter fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;fw.txt&quot;</span>); ) &#123;</span><br><span class="line">            <span class="comment">// 写出数据</span></span><br><span class="line">            fw.write(<span class="string">&quot;黑马程序员&quot;</span>); <span class="comment">//黑马程序员</span></span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="JDK9的改进-扩展知识点了解内容"><a href="#JDK9的改进-扩展知识点了解内容" class="headerlink" title="JDK9的改进(扩展知识点了解内容)"></a>JDK9的改进(扩展知识点了解内容)</h3><p>JDK9中<code>try-with-resource</code> 的改进，对于<strong>引入对象</strong>的方式，支持的更加简洁。被引入的对象，同样可以自动关闭，无需手动close，我们来了解一下格式。</p><p>改进前格式：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 被final修饰的对象</span></span><br><span class="line"><span class="keyword">final</span> Resource resource1 = <span class="keyword">new</span> Resource(<span class="string">&quot;resource1&quot;</span>);</span><br><span class="line"><span class="comment">// 普通对象</span></span><br><span class="line">Resource resource2 = <span class="keyword">new</span> Resource(<span class="string">&quot;resource2&quot;</span>);</span><br><span class="line"><span class="comment">// 引入方式：创建新的变量保存</span></span><br><span class="line"><span class="keyword">try</span> (Resource r1 = resource1;</span><br><span class="line">     Resource r2 = resource2) &#123;</span><br><span class="line">     <span class="comment">// 使用对象</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>改进后格式：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 被final修饰的对象</span></span><br><span class="line"><span class="keyword">final</span> Resource resource1 = <span class="keyword">new</span> Resource(<span class="string">&quot;resource1&quot;</span>);</span><br><span class="line"><span class="comment">// 普通对象</span></span><br><span class="line">Resource resource2 = <span class="keyword">new</span> Resource(<span class="string">&quot;resource2&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 引入方式：直接引入</span></span><br><span class="line"><span class="keyword">try</span> (resource1; resource2) &#123;</span><br><span class="line">     <span class="comment">// 使用对象</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>改进后，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TryDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 创建流对象</span></span><br><span class="line">        <span class="keyword">final</span>  FileReader fr  = <span class="keyword">new</span> FileReader(<span class="string">&quot;in.txt&quot;</span>);</span><br><span class="line">        FileWriter fw = <span class="keyword">new</span> FileWriter(<span class="string">&quot;out.txt&quot;</span>);</span><br><span class="line">        <span class="comment">// 引入到try中</span></span><br><span class="line">        <span class="keyword">try</span> (fr; fw) &#123;</span><br><span class="line">            <span class="comment">// 定义变量</span></span><br><span class="line">            <span class="keyword">int</span> b;</span><br><span class="line">            <span class="comment">// 读取数据</span></span><br><span class="line">            <span class="keyword">while</span> ((b = fr.read())!=-<span class="number">1</span>) &#123;</span><br><span class="line">              <span class="comment">// 写出数据</span></span><br><span class="line">              fw.write(b);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第五章-属性集"><a href="#第五章-属性集" class="headerlink" title="第五章 属性集"></a>第五章 属性集</h1><h2 id="5-1-概述"><a href="#5-1-概述" class="headerlink" title="5.1 概述"></a>5.1 概述</h2><p><code>java.util.Properties </code> 继承于<code> Hashtable</code> ，来表示一个持久的属性集。它使用键值结构存储数据，每个键及其对应值都是一个字符串。该类也被许多Java类使用，比如获取系统属性时，<code>System.getProperties</code> 方法就是返回一个<code>Properties</code>对象。</p><h2 id="5-2-Properties类"><a href="#5-2-Properties类" class="headerlink" title="5.2 Properties类"></a>5.2 Properties类</h2><h3 id="构造方法-4"><a href="#构造方法-4" class="headerlink" title="构造方法"></a>构造方法</h3><ul><li><code>public Properties()</code> :创建一个空的属性列表。</li></ul><h3 id="基本的存储方法"><a href="#基本的存储方法" class="headerlink" title="基本的存储方法"></a>基本的存储方法</h3><ul><li><code>public Object setProperty(String key, String value)</code> ： 保存一对属性。  </li><li><code>public String getProperty(String key) </code> ：使用此属性列表中指定的键搜索属性值。</li><li><code>public Set&lt;String&gt; stringPropertyNames() </code> ：所有键的名称的集合。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ProDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        <span class="comment">// 创建属性集对象</span></span><br><span class="line">        Properties properties = <span class="keyword">new</span> Properties();</span><br><span class="line">        <span class="comment">// 添加键值对元素</span></span><br><span class="line">        properties.setProperty(<span class="string">&quot;filename&quot;</span>, <span class="string">&quot;a.txt&quot;</span>);</span><br><span class="line">        properties.setProperty(<span class="string">&quot;length&quot;</span>, <span class="string">&quot;209385038&quot;</span>);</span><br><span class="line">        properties.setProperty(<span class="string">&quot;location&quot;</span>, <span class="string">&quot;D:\\a.txt&quot;</span>);</span><br><span class="line">        <span class="comment">// 打印属性集对象</span></span><br><span class="line">        System.out.println(properties);</span><br><span class="line">        <span class="comment">// 通过键,获取属性值</span></span><br><span class="line">        System.out.println(properties.getProperty(<span class="string">&quot;filename&quot;</span>));</span><br><span class="line">        System.out.println(properties.getProperty(<span class="string">&quot;length&quot;</span>));</span><br><span class="line">        System.out.println(properties.getProperty(<span class="string">&quot;location&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 遍历属性集,获取所有键的集合</span></span><br><span class="line">        Set&lt;String&gt; strings = properties.stringPropertyNames();</span><br><span class="line">        <span class="comment">// 打印键值对</span></span><br><span class="line">        <span class="keyword">for</span> (String key : strings ) &#123;</span><br><span class="line">            System.out.println(key+<span class="string">&quot; -- &quot;</span>+properties.getProperty(key));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">&#123;filename=a.txt, length=<span class="number">209385038</span>, location=D:\a.txt&#125;</span><br><span class="line">a.txt</span><br><span class="line"><span class="number">209385038</span></span><br><span class="line">D:\a.txt</span><br><span class="line">filename -- a.txt</span><br><span class="line">length -- <span class="number">209385038</span></span><br><span class="line">location -- D:\a.txt</span><br></pre></td></tr></table></figure><h3 id="与流相关的方法"><a href="#与流相关的方法" class="headerlink" title="与流相关的方法"></a>与流相关的方法</h3><ul><li><code>public void load(InputStream inStream)</code>： 从字节输入流中读取键值对。 </li></ul><p>参数中使用了字节输入流，通过流对象，可以关联到某文件上，这样就能够加载文本中的数据了。文本数据格式:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">filename&#x3D;a.txt</span><br><span class="line">length&#x3D;209385038</span><br><span class="line">location&#x3D;D:\a.txt</span><br></pre></td></tr></table></figure><p>加载代码演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ProDemo2</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        <span class="comment">// 创建属性集对象</span></span><br><span class="line">        Properties pro = <span class="keyword">new</span> Properties();</span><br><span class="line">        <span class="comment">// 加载文本中信息到属性集</span></span><br><span class="line">        pro.load(<span class="keyword">new</span> FileInputStream(<span class="string">&quot;read.txt&quot;</span>));</span><br><span class="line">        <span class="comment">// 遍历集合并打印</span></span><br><span class="line">        Set&lt;String&gt; strings = pro.stringPropertyNames();</span><br><span class="line">        <span class="keyword">for</span> (String key : strings ) &#123;</span><br><span class="line">            System.out.println(key+<span class="string">&quot; -- &quot;</span>+pro.getProperty(key));</span><br><span class="line">        &#125;</span><br><span class="line">     &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">filename -- a.txt</span><br><span class="line">length -- <span class="number">209385038</span></span><br><span class="line">location -- D:\a.txt</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：文本中的数据，必须是键值对形式，可以使用空格、等号、冒号等符号分隔。</p></blockquote>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中File类、递归</title>
      <link href="java/javaold/file/"/>
      <url>java/javaold/file/</url>
      
        <content type="html"><![CDATA[<h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li> File类</li><li> 递归</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><ul><li><input disabled="" type="checkbox"> 能够说出File对象的创建方式</li><li><input disabled="" type="checkbox"> 能够说出File类获取名称的方法名称</li><li><input disabled="" type="checkbox"> 能够说出File类获取绝对路径的方法名称</li><li><input disabled="" type="checkbox"> 能够说出File类获取文件大小的方法名称</li><li><input checked="" disabled="" type="checkbox"> 能够说出File类判断是否是文件的方法名称</li><li><input disabled="" type="checkbox"> 能够说出File类判断是否是文件夹的方法名称</li><li><input disabled="" type="checkbox"> 能够辨别相对路径和绝对路径</li><li><input checked="" disabled="" type="checkbox"> 能够遍历文件夹</li><li><input checked="" disabled="" type="checkbox"> 能够解释递归的含义</li><li><input checked="" disabled="" type="checkbox"> 能够使用递归的方式计算5的阶乘</li><li><input disabled="" type="checkbox"> 能够说出使用递归会内存溢出隐患的原因</li></ul><h1 id="第一章-File类"><a href="#第一章-File类" class="headerlink" title="第一章 File类"></a>第一章 File类</h1><h2 id="1-1-概述"><a href="#1-1-概述" class="headerlink" title="1.1 概述"></a>1.1 概述</h2><p><code>java.io.File</code> 类是文件和目录路径名的抽象表示，主要用于文件和目录的创建、查找和删除等操作。</p><h2 id="1-2-构造方法"><a href="#1-2-构造方法" class="headerlink" title="1.2 构造方法"></a>1.2 构造方法</h2><ul><li><code>public File(String pathname) </code> ：通过将给定的<strong>路径名字符串</strong>转换为抽象路径名来创建新的 File实例。  </li><li><code>public File(String parent, String child) </code> ：从<strong>父路径名字符串和子路径名字符串</strong>创建新的 File实例。</li><li><code>public File(File parent, String child)</code> ：从<strong>父抽象路径名和子路径名字符串</strong>创建新的 File实例。  </li></ul><ul><li>构造举例，代码如下：</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 文件路径名</span></span><br><span class="line">String pathname = <span class="string">&quot;D:\\aaa.txt&quot;</span>;</span><br><span class="line">File file1 = <span class="keyword">new</span> File(pathname); </span><br><span class="line"></span><br><span class="line"><span class="comment">// 文件路径名</span></span><br><span class="line">String pathname2 = <span class="string">&quot;D:\\aaa\\bbb.txt&quot;</span>;</span><br><span class="line">File file2 = <span class="keyword">new</span> File(pathname2); </span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过父路径和子路径字符串</span></span><br><span class="line"> String parent = <span class="string">&quot;d:\\aaa&quot;</span>;</span><br><span class="line"> String child = <span class="string">&quot;bbb.txt&quot;</span>;</span><br><span class="line"> File file3 = <span class="keyword">new</span> File(parent, child);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过父级File对象和子路径字符串</span></span><br><span class="line">File parentDir = <span class="keyword">new</span> File(<span class="string">&quot;d:\\aaa&quot;</span>);</span><br><span class="line">String child = <span class="string">&quot;bbb.txt&quot;</span>;</span><br><span class="line">File file4 = <span class="keyword">new</span> File(parentDir, child);</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：</p><ol><li>一个File对象代表硬盘中实际存在的一个文件或者目录。</li><li>无论该路径下是否存在文件或者目录，都不影响File对象的创建。</li></ol></blockquote><h2 id="1-3-常用方法"><a href="#1-3-常用方法" class="headerlink" title="1.3 常用方法"></a>1.3 常用方法</h2><h3 id="获取功能的方法"><a href="#获取功能的方法" class="headerlink" title="获取功能的方法"></a>获取功能的方法</h3><ul><li><p><code>public String getAbsolutePath() </code> ：返回此File的绝对路径名字符串。</p></li><li><p><code>public String getPath()</code> ：将此File转换为路径名字符串。 </p></li><li><p><code>public String getName()</code>  ：返回由此File表示的文件或目录的名称。  </p></li><li><p><code>public long length()</code>  ：返回由此File表示的文件的长度。 </p><p>方法演示，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileGet</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        File f = <span class="keyword">new</span> File(<span class="string">&quot;d:/aaa/bbb.java&quot;</span>);     </span><br><span class="line">        System.out.println(<span class="string">&quot;文件绝对路径:&quot;</span>+f.getAbsolutePath());</span><br><span class="line">        System.out.println(<span class="string">&quot;文件构造路径:&quot;</span>+f.getPath());</span><br><span class="line">        System.out.println(<span class="string">&quot;文件名称:&quot;</span>+f.getName());</span><br><span class="line">        System.out.println(<span class="string">&quot;文件长度:&quot;</span>+f.length()+<span class="string">&quot;字节&quot;</span>);</span><br><span class="line"></span><br><span class="line">        File f2 = <span class="keyword">new</span> File(<span class="string">&quot;d:/aaa&quot;</span>);     </span><br><span class="line">        System.out.println(<span class="string">&quot;目录绝对路径:&quot;</span>+f2.getAbsolutePath());</span><br><span class="line">        System.out.println(<span class="string">&quot;目录构造路径:&quot;</span>+f2.getPath());</span><br><span class="line">        System.out.println(<span class="string">&quot;目录名称:&quot;</span>+f2.getName());</span><br><span class="line">        System.out.println(<span class="string">&quot;目录长度:&quot;</span>+f2.length());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">文件绝对路径:d:\aaa\bbb.java</span><br><span class="line">文件构造路径:d:\aaa\bbb.java</span><br><span class="line">文件名称:bbb.java</span><br><span class="line">文件长度:<span class="number">636</span>字节</span><br><span class="line"></span><br><span class="line">目录绝对路径:d:\aaa</span><br><span class="line">目录构造路径:d:\aaa</span><br><span class="line">目录名称:aaa</span><br><span class="line">目录长度:<span class="number">4096</span></span><br></pre></td></tr></table></figure></li></ul><blockquote><p>API中说明：length()，表示文件的长度。但是File对象表示目录，则返回值未指定。</p></blockquote><h3 id="绝对路径和相对路径"><a href="#绝对路径和相对路径" class="headerlink" title="绝对路径和相对路径"></a>绝对路径和相对路径</h3><ul><li><strong>绝对路径</strong>：从盘符开始的路径，这是一个完整的路径。</li><li><strong>相对路径</strong>：相对于项目目录的路径，这是一个便捷的路径，开发中经常使用。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FilePath</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// D盘下的bbb.java文件</span></span><br><span class="line">        File f = <span class="keyword">new</span> File(<span class="string">&quot;D:\\bbb.java&quot;</span>);</span><br><span class="line">        System.out.println(f.getAbsolutePath());</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 项目下的bbb.java文件</span></span><br><span class="line">        File f2 = <span class="keyword">new</span> File(<span class="string">&quot;bbb.java&quot;</span>);</span><br><span class="line">        System.out.println(f2.getAbsolutePath());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">D:\bbb.java</span><br><span class="line">D:\idea_project_test4\bbb.java</span><br></pre></td></tr></table></figure><h3 id="判断功能的方法"><a href="#判断功能的方法" class="headerlink" title="判断功能的方法"></a>判断功能的方法</h3><ul><li><code>public boolean exists()</code> ：此File表示的文件或目录是否实际存在。</li><li><code>public boolean isDirectory()</code> ：此File表示的是否为目录。</li><li><code>public boolean isFile()</code> ：此File表示的是否为文件。</li></ul><p>方法演示，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileIs</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        File f = <span class="keyword">new</span> File(<span class="string">&quot;d:\\aaa\\bbb.java&quot;</span>);</span><br><span class="line">        File f2 = <span class="keyword">new</span> File(<span class="string">&quot;d:\\aaa&quot;</span>);</span><br><span class="line">        <span class="comment">// 判断是否存在</span></span><br><span class="line">        System.out.println(<span class="string">&quot;d:\\aaa\\bbb.java 是否存在:&quot;</span>+f.exists());</span><br><span class="line">        System.out.println(<span class="string">&quot;d:\\aaa 是否存在:&quot;</span>+f2.exists());</span><br><span class="line">        <span class="comment">// 判断是文件还是目录</span></span><br><span class="line">        System.out.println(<span class="string">&quot;d:\\aaa 文件?:&quot;</span>+f2.isFile());</span><br><span class="line">        System.out.println(<span class="string">&quot;d:\\aaa 目录?:&quot;</span>+f2.isDirectory());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">输出结果：</span><br><span class="line">d:\aaa\bbb.java 是否存在:<span class="keyword">true</span></span><br><span class="line">d:\aaa 是否存在:<span class="keyword">true</span></span><br><span class="line">d:\aaa 文件?:<span class="keyword">false</span></span><br><span class="line">d:\aaa 目录?:<span class="keyword">true</span></span><br></pre></td></tr></table></figure><h3 id="创建删除功能的方法"><a href="#创建删除功能的方法" class="headerlink" title="创建删除功能的方法"></a>创建删除功能的方法</h3><ul><li><code>public boolean createNewFile()</code> ：当且仅当具有该名称的文件尚不存在时，创建一个新的空文件。 </li><li><code>public boolean delete()</code> ：删除由此File表示的文件或目录。  </li><li><code>public boolean mkdir()</code> ：创建由此File表示的目录。</li><li><code>public boolean mkdirs()</code> ：创建由此File表示的目录，包括任何必需但不存在的父目录。</li></ul><p>方法演示，代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileCreateDelete</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 文件的创建</span></span><br><span class="line">        File f = <span class="keyword">new</span> File(<span class="string">&quot;aaa.txt&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;是否存在:&quot;</span>+f.exists()); <span class="comment">// false</span></span><br><span class="line">        System.out.println(<span class="string">&quot;是否创建:&quot;</span>+f.createNewFile()); <span class="comment">// true</span></span><br><span class="line">        System.out.println(<span class="string">&quot;是否存在:&quot;</span>+f.exists()); <span class="comment">// true</span></span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 目录的创建</span></span><br><span class="line">        File f2= <span class="keyword">new</span> File(<span class="string">&quot;newDir&quot;</span>);    </span><br><span class="line">        System.out.println(<span class="string">&quot;是否存在:&quot;</span>+f2.exists());<span class="comment">// false</span></span><br><span class="line">        System.out.println(<span class="string">&quot;是否创建:&quot;</span>+f2.mkdir()); <span class="comment">// true</span></span><br><span class="line">        System.out.println(<span class="string">&quot;是否存在:&quot;</span>+f2.exists());<span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 创建多级目录</span></span><br><span class="line">        File f3= <span class="keyword">new</span> File(<span class="string">&quot;newDira\\newDirb&quot;</span>);</span><br><span class="line">        System.out.println(f3.mkdir());<span class="comment">// false</span></span><br><span class="line">        File f4= <span class="keyword">new</span> File(<span class="string">&quot;newDira\\newDirb&quot;</span>);</span><br><span class="line">        System.out.println(f4.mkdirs());<span class="comment">// true</span></span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 文件的删除</span></span><br><span class="line">        System.out.println(f.delete());<span class="comment">// true</span></span><br><span class="line">      </span><br><span class="line">        <span class="comment">// 目录的删除</span></span><br><span class="line">        System.out.println(f2.delete());<span class="comment">// true</span></span><br><span class="line">        System.out.println(f4.delete());<span class="comment">// false</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>API中说明：delete方法，如果此File表示目录，则目录必须为空才能删除。</p></blockquote><h2 id="1-4-目录的遍历"><a href="#1-4-目录的遍历" class="headerlink" title="1.4 目录的遍历"></a>1.4 目录的遍历</h2><ul><li><code>public String[] list()</code> ：返回一个String数组，表示该File目录中的所有子文件或目录。</li></ul><ul><li><code>public File[] listFiles()</code> ：返回一个File数组，表示该File目录中的所有的子文件或目录。  </li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FileFor</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        File dir = <span class="keyword">new</span> File(<span class="string">&quot;d:\\java_code&quot;</span>);</span><br><span class="line">      </span><br><span class="line">        <span class="comment">//获取当前目录下的文件以及文件夹的名称。</span></span><br><span class="line">        String[] names = dir.list();</span><br><span class="line">        <span class="keyword">for</span>(String name : names)&#123;</span><br><span class="line">            System.out.println(name);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//获取当前目录下的文件以及文件夹对象，只要拿到了文件对象，那么就可以获取更多信息</span></span><br><span class="line">        File[] files = dir.listFiles();</span><br><span class="line">        <span class="keyword">for</span> (File file : files) &#123;</span><br><span class="line">            System.out.println(file);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：</p><p>调用listFiles方法的File对象，表示的必须是实际存在的目录，否则返回null，无法进行遍历。</p></blockquote><h1 id="第二章-递归"><a href="#第二章-递归" class="headerlink" title="第二章 递归"></a>第二章 递归</h1><h2 id="2-1-概述"><a href="#2-1-概述" class="headerlink" title="2.1 概述"></a>2.1 概述</h2><ul><li><p><strong>递归</strong>：指在当前方法内调用自己的这种现象。</p></li><li><p><strong>递归的分类:</strong></p><ul><li>递归分为两种，直接递归和间接递归。</li><li>直接递归称为方法自身调用自己。</li><li>间接递归可以A方法调用B方法，B方法调用C方法，C方法调用A方法。</li></ul></li><li><p><strong>注意事项</strong>：</p><ul><li>递归一定要有条件限定，保证递归能够停止下来，否则会发生栈内存溢出。</li><li>在递归中虽然有限定条件，但是递归次数不能太多。否则也会发生栈内存溢出。</li><li>构造方法,禁止递归</li></ul></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01DiGui</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// a();</span></span><br><span class="line">        b(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 3.构造方法,禁止递归</span></span><br><span class="line"><span class="comment">     * 编译报错:构造方法是创建对象使用的,不能让对象一直创建下去</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Demo01DiGui</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">//Demo01DiGui();</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 2.在递归中虽然有限定条件，但是递归次数不能太多。否则也会发生栈内存溢出。</span></span><br><span class="line"><span class="comment">     * 4993</span></span><br><span class="line"><span class="comment">     *  Exception in thread &quot;main&quot; java.lang.StackOverflowError</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">b</span><span class="params">(<span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">        System.out.println(i);</span><br><span class="line">        <span class="comment">//添加一个递归结束的条件,i==5000的时候结束</span></span><br><span class="line">        <span class="keyword">if</span>(i==<span class="number">5000</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span>;<span class="comment">//结束方法</span></span><br><span class="line">        &#125;</span><br><span class="line">        b(++i);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 1.递归一定要有条件限定，保证递归能够停止下来，否则会发生栈内存溢出。 Exception in thread &quot;main&quot;</span></span><br><span class="line"><span class="comment">     * java.lang.StackOverflowError</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">a</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;a方法&quot;</span>);</span><br><span class="line">        a();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="2-2-递归累加求和"><a href="#2-2-递归累加求和" class="headerlink" title="2.2 递归累加求和"></a>2.2 递归累加求和</h2><h3 id="计算1-n的和"><a href="#计算1-n的和" class="headerlink" title="计算1 ~ n的和"></a>计算1 ~ n的和</h3><p><strong>分析</strong>：num的累和 = num + (num-1)的累和，所以可以把累和的操作定义成一个方法，递归调用。</p><p><strong>实现代码</strong>：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DiGuiDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//计算1~num的和，使用递归完成</span></span><br><span class="line">        <span class="keyword">int</span> num = <span class="number">5</span>;</span><br><span class="line">        <span class="comment">// 调用求和的方法</span></span><br><span class="line">        <span class="keyword">int</span> sum = getSum(num);</span><br><span class="line">        <span class="comment">// 输出结果</span></span><br><span class="line">        System.out.println(sum);</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">      通过递归算法实现.</span></span><br><span class="line"><span class="comment">      参数列表:int </span></span><br><span class="line"><span class="comment">      返回值类型: int </span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getSum</span><span class="params">(<span class="keyword">int</span> num)</span> </span>&#123;</span><br><span class="line">        <span class="comment">/* </span></span><br><span class="line"><span class="comment">           num为1时,方法返回1,</span></span><br><span class="line"><span class="comment">           相当于是方法的出口,num总有是1的情况</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line">        <span class="keyword">if</span>(num == <span class="number">1</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">          num不为1时,方法返回 num +(num-1)的累和</span></span><br><span class="line"><span class="comment">          递归调用getSum方法</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line">        <span class="keyword">return</span> num + getSum(num-<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="代码执行图解"><a href="#代码执行图解" class="headerlink" title="代码执行图解"></a>代码执行图解</h3><p><img src= "/img/loading.gif" data-lazy-src="img/day08_01_%E9%80%92%E5%BD%92%E7%B4%AF%E5%92%8C.jpg"></p><blockquote><p>小贴士：递归一定要有条件限定，保证递归能够停止下来，次数不要太多，否则会发生栈内存溢出。</p></blockquote><h2 id="2-3-递归求阶乘"><a href="#2-3-递归求阶乘" class="headerlink" title="2.3 递归求阶乘"></a>2.3 递归求阶乘</h2><ul><li><strong>阶乘</strong>：所有小于及等于该数的正整数的积。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">n的阶乘：n! = n * (n-<span class="number">1</span>) *...* <span class="number">3</span> * <span class="number">2</span> * <span class="number">1</span> </span><br></pre></td></tr></table></figure><p><strong>分析</strong>：这与累和类似,只不过换成了乘法运算，学员可以自己练习，需要注意阶乘值符合int类型的范围。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">推理得出：n! &#x3D; n * (n-1)!</span><br></pre></td></tr></table></figure><p><strong>代码实现</strong>：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DiGuiDemo</span> </span>&#123;</span><br><span class="line">    <span class="comment">//计算n的阶乘，使用递归完成</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">3</span>;</span><br><span class="line">        <span class="comment">// 调用求阶乘的方法</span></span><br><span class="line">        <span class="keyword">int</span> value = getValue(n);</span><br><span class="line">        <span class="comment">// 输出结果</span></span><br><span class="line">        System.out.println(<span class="string">&quot;阶乘为:&quot;</span>+ value);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">      通过递归算法实现.</span></span><br><span class="line"><span class="comment">      参数列表:int </span></span><br><span class="line"><span class="comment">      返回值类型: int </span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getValue</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 1的阶乘为1</span></span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">          n不为1时,方法返回 n! = n*(n-1)!</span></span><br><span class="line"><span class="comment">          递归调用getValue方法</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line">        <span class="keyword">return</span> n * getValue(n - <span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="2-4-递归打印多级目录"><a href="#2-4-递归打印多级目录" class="headerlink" title="2.4 递归打印多级目录"></a>2.4 递归打印多级目录</h2><p><strong>分析</strong>：多级目录的打印，就是当目录的嵌套。遍历之前，无从知道到底有多少级目录，所以我们还是要使用递归实现。</p><p><strong>代码实现</strong>：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DiGuiDemo2</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建File对象</span></span><br><span class="line">        File dir  = <span class="keyword">new</span> File(<span class="string">&quot;D:\\aaa&quot;</span>);</span><br><span class="line">        <span class="comment">// 调用打印目录方法</span></span><br><span class="line">        printDir(dir);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span>  <span class="title">printDir</span><span class="params">(File dir)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 获取子文件和目录</span></span><br><span class="line">        File[] files = dir.listFiles();</span><br><span class="line">        <span class="comment">// 循环打印</span></span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">          判断:</span></span><br><span class="line"><span class="comment">          当是文件时,打印绝对路径.</span></span><br><span class="line"><span class="comment">          当是目录时,继续调用打印目录的方法,形成递归调用.</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line">        <span class="keyword">for</span> (File file : files) &#123;</span><br><span class="line">            <span class="comment">// 判断</span></span><br><span class="line">            <span class="keyword">if</span> (file.isFile()) &#123;</span><br><span class="line">                <span class="comment">// 是文件,输出文件绝对路径</span></span><br><span class="line">                System.out.println(<span class="string">&quot;文件名:&quot;</span>+ file.getAbsolutePath());</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// 是目录,输出目录绝对路径</span></span><br><span class="line">                System.out.println(<span class="string">&quot;目录:&quot;</span>+file.getAbsolutePath());</span><br><span class="line">                <span class="comment">// 继续遍历,调用printDir,形成递归</span></span><br><span class="line">                printDir(file);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第三章-综合案例"><a href="#第三章-综合案例" class="headerlink" title="第三章 综合案例"></a>第三章 综合案例</h1><h2 id="3-1-文件搜索"><a href="#3-1-文件搜索" class="headerlink" title="3.1 文件搜索"></a>3.1 文件搜索</h2><p>搜索<code>D:\aaa</code> 目录中的<code>.java</code> 文件。</p><p><strong>分析</strong>：</p><ol><li>目录搜索，无法判断多少级目录，所以使用递归，遍历所有目录。</li><li>遍历目录时，获取的子文件，通过文件名称，判断是否符合条件。</li></ol><p><strong>代码实现</strong>：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DiGuiDemo3</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建File对象</span></span><br><span class="line">        File dir  = <span class="keyword">new</span> File(<span class="string">&quot;D:\\aaa&quot;</span>);</span><br><span class="line">        <span class="comment">// 调用打印目录方法</span></span><br><span class="line">        printDir(dir);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">printDir</span><span class="params">(File dir)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 获取子文件和目录</span></span><br><span class="line">        File[] files = dir.listFiles();</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 循环打印</span></span><br><span class="line">        <span class="keyword">for</span> (File file : files) &#123;</span><br><span class="line">            <span class="keyword">if</span> (file.isFile()) &#123;</span><br><span class="line">                <span class="comment">// 是文件，判断文件名并输出文件绝对路径</span></span><br><span class="line">                <span class="keyword">if</span> (file.getName().endsWith(<span class="string">&quot;.java&quot;</span>)) &#123;</span><br><span class="line">                    System.out.println(<span class="string">&quot;文件名:&quot;</span> + file.getAbsolutePath());</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// 是目录，继续遍历,形成递归</span></span><br><span class="line">                printDir(file);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-2-文件过滤器优化"><a href="#3-2-文件过滤器优化" class="headerlink" title="3.2 文件过滤器优化"></a>3.2 文件过滤器优化</h2><p><code>java.io.FileFilter</code>是一个接口，是File的过滤器。 该接口的对象可以传递给File类的<code>listFiles(FileFilter)</code> 作为参数， 接口中只有一个方法。</p><p><code>boolean accept(File pathname)  </code> ：测试pathname是否应该包含在当前File目录中，符合则返回true。</p><p><strong>分析</strong>：</p><ol><li>接口作为参数，需要传递子类对象，重写其中方法。我们选择匿名内部类方式，比较简单。</li><li><code>accept</code>方法，参数为File，表示当前File下所有的子文件和子目录。保留住则返回true，过滤掉则返回false。保留规则：<ol><li>要么是.java文件。</li><li>要么是目录，用于继续遍历。</li></ol></li><li>通过过滤器的作用，<code>listFiles(FileFilter)</code>返回的数组元素中，子文件对象都是符合条件的，可以直接打印。</li></ol><p><strong>代码实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DiGuiDemo4</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        File dir = <span class="keyword">new</span> File(<span class="string">&quot;D:\\aaa&quot;</span>);</span><br><span class="line">        printDir2(dir);</span><br><span class="line">    &#125;</span><br><span class="line">  </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">printDir2</span><span class="params">(File dir)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 匿名内部类方式,创建过滤器子类对象</span></span><br><span class="line">        File[] files = dir.listFiles(<span class="keyword">new</span> FileFilter() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">accept</span><span class="params">(File pathname)</span> </span>&#123;</span><br><span class="line">                <span class="keyword">return</span> pathname.getName().endsWith(<span class="string">&quot;.java&quot;</span>)||pathname.isDirectory();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="comment">// 循环打印</span></span><br><span class="line">        <span class="keyword">for</span> (File file : files) &#123;</span><br><span class="line">            <span class="keyword">if</span> (file.isFile()) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;文件名:&quot;</span> + file.getAbsolutePath());</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                printDir2(file);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;      </span><br></pre></td></tr></table></figure><h2 id="3-3-Lambda优化"><a href="#3-3-Lambda优化" class="headerlink" title="3.3 Lambda优化"></a>3.3 Lambda优化</h2><p><strong>分析：</strong><code>FileFilter</code>是只有一个方法的接口，因此可以用lambda表达式简写。</p><p>lambda格式：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">()-&gt;&#123; &#125;</span><br></pre></td></tr></table></figure><p><strong>代码实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">printDir3</span><span class="params">(File dir)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// lambda的改写</span></span><br><span class="line">    File[] files = dir.listFiles(f -&gt;&#123; </span><br><span class="line">        <span class="keyword">return</span> f.getName().endsWith(<span class="string">&quot;.java&quot;</span>) || f.isDirectory(); </span><br><span class="line">    &#125;);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 循环打印</span></span><br><span class="line">    <span class="keyword">for</span> (File file : files) &#123;</span><br><span class="line">        <span class="keyword">if</span> (file.isFile()) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;文件名:&quot;</span> + file.getAbsolutePath());</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            printDir3(file);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>servlet的配置以及使用</title>
      <link href="java/javaold/servlet/"/>
      <url>java/javaold/servlet/</url>
      
        <content type="html"><![CDATA[<h2 id="servlet-server-applet"><a href="#servlet-server-applet" class="headerlink" title="servlet:server applet"></a>servlet:server applet</h2><h3 id="概念-运行在服务器端的小程序"><a href="#概念-运行在服务器端的小程序" class="headerlink" title="* 概念:运行在服务器端的小程序"></a>* 概念:运行在服务器端的小程序</h3><ul><li>servlet就是一个接口,定义了java类被浏览器访问到(tomcat)识别的规则.</li><li>将来我们自定义一个类,实现servlet接口,复写方法.</li></ul><h3 id="快速入门"><a href="#快速入门" class="headerlink" title="* 快速入门:"></a>* 快速入门:</h3><ol><li>创建一个JavaEE项目<br>javaee7,tomcat路径配置</li><li>定义一个类,实现servlet接口 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ServletDemo1</span> <span class="keyword">implements</span> <span class="title">Servlet</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 重写方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>实现接口中的抽象方法<br>alt+enter</li><li>配置servlet</li></ol><p>在web.xml中配置</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--    配置servlet--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">servlet</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet-name</span>&gt;</span>demo1<span class="tag">&lt;/<span class="name">servlet-name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet-class</span>&gt;</span>cn.itcast.web.servlet.ServletDemo1<span class="tag">&lt;/<span class="name">servlet-class</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">servlet</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--    写mapping--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">servlet-mapping</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet-name</span>&gt;</span>demo1<span class="tag">&lt;/<span class="name">servlet-name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/demo1<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">servlet-mapping</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="执行原理"><a href="#执行原理" class="headerlink" title="执行原理:"></a>执行原理:</h3><ol><li>当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的servlet的资源路径</li><li>查找web.xml文件,是否有对应的<code>&lt;url-pattern&gt;</code>标签体内容.</li><li>如果有,则在找到对应的<code>&lt;servlet-class&gt;</code>全类名</li><li>tomcat会将字节码文件加载进内存,并且创建其对象</li><li>调用其方法</li></ol><h3 id="servlet-中的方法-中的生命周期"><a href="#servlet-中的方法-中的生命周期" class="headerlink" title="servlet(中的方法)中的生命周期"></a>servlet(中的方法)中的生命周期</h3><ol><li>被创建: 执行init方法,只执行一次<ul><li>servlet什么时候被创建?<ul><li>默认情况下,第一次被访问时, servlet被创建</li><li>可以配置执行servlet的创建时机<ul><li>在<code>&lt;servlet&gt;</code>标签下配置<ol><li>第一次被访问时, 创建<ul><li><code>&lt;load-on-startup&gt;</code>的值为负数</li></ul></li><li>在服务器启动时, 创建<ul><li><code>&lt;load-on-startup&gt;</code>的值为0或者正整数</li></ul></li></ol></li></ul></li></ul></li><li>Servlet的<code>init</code>方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的<ul><li>多个用户同时访问时,可能存在线程安全问题</li><li>解决: 尽量不要在Servlet中定义成员变量.即使定义了成员变量,也不要对修改值</li></ul></li></ul></li><li>提供服务: 执行service方法, 执行多次<ul><li>每次访问<code>Servlet</code>时,Service方法都会被调用一次</li></ul></li><li>被销毁: 执行destroy方法,只执行一次<ul><li>Servlet被销毁时执行.服务器关闭时,Servlet被销毁</li><li>只有服务器正常关闭时,才会执行destroy方法</li><li>destroy方法在Servlet被销毁之前执行,一般用于释放资源(遗言一般死之前说)</li></ul></li></ol><ul><li>Servlet3.0 :<ul><li>好处:<ul><li>支持注解配置.可以不需要web.xml了</li></ul></li><li>步骤:<ol><li>创建javaEE项目,选择Servlet的版本3.0以上,可以不创建<code>web.xml</code></li><li>定义一个类,实现Servlet接口</li><li>重写方法</li><li>在类上使用<code>@webservlet</code>注解,进行配置<ul><li><code>@WebServlet(&quot;资源路径)</code></li></ul></li></ol></li></ul></li></ul><h3 id="IDEA与tomacat的相关配置"><a href="#IDEA与tomacat的相关配置" class="headerlink" title="IDEA与tomacat的相关配置"></a>IDEA与tomacat的相关配置</h3><ol><li>IDEA会为每个tomcat部署的项目单独建立一份配置文件<ul><li>查看控制台的log:<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Using CATALINA_BASE:   &quot;C:\Users\yangxin\.IntelliJIdea2019.<span class="number">2</span>\system\tomcat\Tomcat_8_5_47_java_web_2&quot;</span><br></pre></td></tr></table></figure></li></ul></li><li>工作空间项目 和 tomcat部署的web项目    <ul><li>tomcat 真正访问的是”tomcat部署的web项目”,”tomcat部署的web项目”对应着”工作空间项目”的web目录下的所有资源</li><li>WEB-INF目录下的资源不能被浏览器直接访问</li></ul></li><li>断点调试:使用”小虫子”启动(debug启动)</li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中线程池、Lambda表达式</title>
      <link href="java/javaold/thread-lambda/"/>
      <url>java/javaold/thread-lambda/</url>
      
        <content type="html"><![CDATA[<h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li>  等待与唤醒案例</li><li>  线程池</li><li>  Lambda表达式</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><p>-[ ] 能够理解线程通信概念<br>-[ ] 能够理解等待唤醒机制<br>-[ ] 能够描述Java中线程池运行原理<br>-[ ] 能够理解函数式编程相对于面向对象的优点<br>-[ ] 能够掌握Lambda表达式的标准格式<br>-[ ] 能够使用Lambda标准格式使用Runnable与Comparator接口<br>-[ ] 能够掌握Lambda表达式的省略格式与规则<br>-[ ] 能够使用Lambda省略格式使用Runnable与Comparator接口<br>-[ ] 能够通过Lambda的标准格式使用自定义的接口（有且仅有一个抽象方法）<br>-[ ] 能够通过Lambda的省略格式使用自定义的接口（有且仅有一个抽象方法）<br>-[ ] 能够明确Lambda的两项使用前提</p><h1 id="第一章-等待唤醒机制"><a href="#第一章-等待唤醒机制" class="headerlink" title="第一章 等待唤醒机制"></a>第一章 等待唤醒机制</h1><h2 id="1-1-线程间通信"><a href="#1-1-线程间通信" class="headerlink" title="1.1 线程间通信"></a>1.1 线程间通信</h2><p><strong>概念：</strong>多个线程在处理同一个资源，但是处理的动作（线程的任务）却不相同。</p><p>比如：线程A用来生成包子的，线程B用来吃包子的，包子可以理解为同一资源，线程A与线程B处理的动作，一个是生产，一个是消费，那么线程A与线程B之间就存在线程通信问题。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E7%BA%BF%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1.bmp"></p><p><strong>为什么要处理线程间通信：</strong></p><p>多个线程并发执行时, 在默认情况下CPU是随机切换线程的，当我们需要多个线程来共同完成一件任务，并且我们希望他们有规律的执行, 那么多线程之间需要一些协调通信，以此来帮我们达到多线程共同操作一份数据。</p><p><strong>如何保证线程间通信有效利用资源：</strong></p><p>多个线程在处理同一个资源，并且任务不同时，需要线程通信来帮助解决线程之间对同一个变量的使用或操作。 就是多个线程在操作同一份数据时， 避免对同一共享变量的争夺。也就是我们需要通过一定的手段使各个线程能有效的利用资源。而这种手段即—— <strong>等待唤醒机制。</strong></p><h2 id="1-2-等待唤醒机制"><a href="#1-2-等待唤醒机制" class="headerlink" title="1.2 等待唤醒机制"></a>1.2 等待唤醒机制</h2><p><strong>什么是等待唤醒机制</strong></p><p>这是多个线程间的一种<strong>协作</strong>机制。谈到线程我们经常想到的是线程间的<strong>竞争（race）</strong>，比如去争夺锁，但这并不是故事的全部，线程间也会有协作机制。就好比在公司里你和你的同事们，你们可能存在在晋升时的竞争，但更多时候你们更多是一起合作以完成某些任务。</p><p>就是在一个线程进行了规定操作后，就进入等待状态（**wait()<strong>）， 等待其他线程执行完他们的指定代码过后 再将其唤醒（</strong>notify()**）;在有多个线程进行等待时， 如果需要，可以使用 notifyAll()来唤醒所有的等待线程。</p><p>wait/notify 就是线程间的一种协作机制。</p><p><strong>等待唤醒中的方法</strong></p><p>等待唤醒机制就是用于解决线程间通信的问题的，使用到的3个方法的含义如下：</p><ol><li>wait：线程不再活动，不再参与调度，进入 wait set 中，因此不会浪费 CPU 资源，也不会去竞争锁了，这时的线程状态即是 WAITING。它还要等着别的线程执行一个<strong>特别的动作</strong>，也即是“<strong>通知（notify）</strong>”在这个对象上等待的线程从wait set 中释放出来，重新进入到调度队列（ready queue）中</li><li>notify：则选取所通知对象的 wait set 中的一个线程释放；例如，餐馆有空位置后，等候就餐最久的顾客最先入座。</li><li>notifyAll：则释放所通知对象的 wait set 上的全部线程。</li></ol><blockquote><p>注意：</p><p>哪怕只通知了一个等待的线程，被通知线程也不能立即恢复执行，因为它当初中断的地方是在同步块内，而此刻它已经不持有锁，所以她需要再次尝试去获取锁（很可能面临其它线程的竞争），成功后才能在当初调用 wait 方法之后的地方恢复执行。</p><p>总结如下：</p><ul><li>如果能获取锁，线程就从 WAITING 状态变成 RUNNABLE 状态；</li><li>否则，从 wait set 出来，又进入 entry set，线程就从 WAITING 状态又变成 BLOCKED 状态</li></ul></blockquote><p><strong>调用wait和notify方法需要注意的细节</strong></p><ol><li>wait方法与notify方法必须要由同一个锁对象调用。因为：对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程。</li><li>wait方法与notify方法是属于Object类的方法的。因为：锁对象可以是任意对象，而任意对象的所属类都是继承了Object类的。</li><li>wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为：必须要通过锁对象调用这2个方法。</li></ol><h2 id="1-3-生产者与消费者问题"><a href="#1-3-生产者与消费者问题" class="headerlink" title="1.3 生产者与消费者问题"></a>1.3 生产者与消费者问题</h2><p>等待唤醒机制其实就是经典的“生产者与消费者”的问题。</p><p>就拿生产包子消费包子来说等待唤醒机制如何有效利用资源：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">包子铺线程生产包子，吃货线程消费包子。当包子没有时（包子状态为<span class="keyword">false</span>），吃货线程等待，包子铺线程生产包子（即包子状态为<span class="keyword">true</span>），并通知吃货线程（解除吃货的等待状态）,因为已经有包子了，那么包子铺线程进入等待状态。接下来，吃货线程能否进一步执行则取决于锁的获取情况。如果吃货获取到锁，那么就执行吃包子动作，包子吃完（包子状态为<span class="keyword">false</span>），并通知包子铺线程（解除包子铺的等待状态）,吃货线程进入等待。包子铺线程能否进一步执行则取决于锁的获取情况。</span><br></pre></td></tr></table></figure><p><strong>代码演示：</strong></p><p>包子资源类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BaoZi</span> </span>&#123;</span><br><span class="line">     String  pier ;</span><br><span class="line">     String  xianer ;</span><br><span class="line">     <span class="keyword">boolean</span>  flag = <span class="keyword">false</span> ;<span class="comment">//包子资源 是否存在  包子资源状态</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>吃货线程类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ChiHuo</span> <span class="keyword">extends</span> <span class="title">Thread</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> BaoZi bz;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">ChiHuo</span><span class="params">(String name,BaoZi bz)</span></span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(name);</span><br><span class="line">        <span class="keyword">this</span>.bz = bz;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">while</span>(<span class="keyword">true</span>)&#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (bz)&#123;</span><br><span class="line">                <span class="keyword">if</span>(bz.flag == <span class="keyword">false</span>)&#123;<span class="comment">//没包子</span></span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        bz.wait();</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                        e.printStackTrace();</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">                System.out.println(<span class="string">&quot;吃货正在吃&quot;</span>+bz.pier+bz.xianer+<span class="string">&quot;包子&quot;</span>);</span><br><span class="line">                bz.flag = <span class="keyword">false</span>;</span><br><span class="line">                bz.notify();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>包子铺线程类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BaoZiPu</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> BaoZi bz;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">BaoZiPu</span><span class="params">(String name,BaoZi bz)</span></span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(name);</span><br><span class="line">        <span class="keyword">this</span>.bz = bz;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">        <span class="comment">//造包子</span></span><br><span class="line">        <span class="keyword">while</span>(<span class="keyword">true</span>)&#123;</span><br><span class="line">            <span class="comment">//同步</span></span><br><span class="line">            <span class="keyword">synchronized</span> (bz)&#123;</span><br><span class="line">                <span class="keyword">if</span>(bz.flag == <span class="keyword">true</span>)&#123;<span class="comment">//包子资源  存在</span></span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line"></span><br><span class="line">                        bz.wait();</span><br><span class="line"></span><br><span class="line">                    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                        e.printStackTrace();</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 没有包子  造包子</span></span><br><span class="line">                System.out.println(<span class="string">&quot;包子铺开始做包子&quot;</span>);</span><br><span class="line">                <span class="keyword">if</span>(count%<span class="number">2</span> == <span class="number">0</span>)&#123;</span><br><span class="line">                    <span class="comment">// 冰皮  五仁</span></span><br><span class="line">                    bz.pier = <span class="string">&quot;冰皮&quot;</span>;</span><br><span class="line">                    bz.xianer = <span class="string">&quot;五仁&quot;</span>;</span><br><span class="line">                &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                    <span class="comment">// 薄皮  牛肉大葱</span></span><br><span class="line">                    bz.pier = <span class="string">&quot;薄皮&quot;</span>;</span><br><span class="line">                    bz.xianer = <span class="string">&quot;牛肉大葱&quot;</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                count++;</span><br><span class="line"></span><br><span class="line">                bz.flag=<span class="keyword">true</span>;</span><br><span class="line">                System.out.println(<span class="string">&quot;包子造好了：&quot;</span>+bz.pier+bz.xianer);</span><br><span class="line">                System.out.println(<span class="string">&quot;吃货来吃吧&quot;</span>);</span><br><span class="line">                <span class="comment">//唤醒等待线程 （吃货）</span></span><br><span class="line">                bz.notify();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//等待唤醒案例</span></span><br><span class="line">        BaoZi bz = <span class="keyword">new</span> BaoZi();</span><br><span class="line"></span><br><span class="line">        ChiHuo ch = <span class="keyword">new</span> ChiHuo(<span class="string">&quot;吃货&quot;</span>,bz);</span><br><span class="line">        BaoZiPu bzp = <span class="keyword">new</span> BaoZiPu(<span class="string">&quot;包子铺&quot;</span>,bz);</span><br><span class="line"></span><br><span class="line">        ch.start();</span><br><span class="line">        bzp.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>执行效果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">包子铺开始做包子</span><br><span class="line">包子造好了：冰皮五仁</span><br><span class="line">吃货来吃吧</span><br><span class="line">吃货正在吃冰皮五仁包子</span><br><span class="line">包子铺开始做包子</span><br><span class="line">包子造好了：薄皮牛肉大葱</span><br><span class="line">吃货来吃吧</span><br><span class="line">吃货正在吃薄皮牛肉大葱包子</span><br><span class="line">包子铺开始做包子</span><br><span class="line">包子造好了：冰皮五仁</span><br><span class="line">吃货来吃吧</span><br><span class="line">吃货正在吃冰皮五仁包子</span><br></pre></td></tr></table></figure><h1 id="第二章-线程池"><a href="#第二章-线程池" class="headerlink" title="第二章 线程池"></a>第二章 线程池</h1><h2 id="2-1-线程池思想概述"><a href="#2-1-线程池思想概述" class="headerlink" title="2.1 线程池思想概述"></a>2.1 线程池思想概述</h2><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E6%B8%B8%E6%B3%B3%E6%B1%A0.jpg"></p><p>我们使用线程的时候就去创建一个线程，这样实现起来非常简便，但是就会有一个问题：</p><p>如果并发的线程数量很多，并且每个线程都是执行一个时间很短的任务就结束了，这样频繁创建线程就会大大降低系统的效率，因为频繁创建线程和销毁线程需要时间。</p><p>那么有没有一种办法使得线程可以复用，就是执行完一个任务，并不被销毁，而是可以继续执行其他的任务？</p><p>在Java中可以通过线程池来达到这样的效果。今天我们就来详细讲解一下Java的线程池。</p><h2 id="2-2-线程池概念"><a href="#2-2-线程池概念" class="headerlink" title="2.2 线程池概念"></a>2.2 线程池概念</h2><ul><li><strong>线程池：</strong>其实就是一个容纳多个线程的容器，其中的线程可以反复使用，省去了频繁创建线程对象的操作，无需反复创建线程而消耗过多资源。</li></ul><p>由于线程池中有很多操作都是与优化资源相关的，我们在这里就不多赘述。我们通过一张图来了解线程池的工作原理：</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%8E%9F%E7%90%86.bmp"></p><p>合理利用线程池能够带来三个好处：</p><ol><li>降低资源消耗。减少了创建和销毁线程的次数，每个工作线程都可以被重复利用，可执行多个任务。</li><li>提高响应速度。当任务到达时，任务可以不需要的等到线程创建就能立即执行。</li><li>提高线程的可管理性。可以根据系统的承受能力，调整线程池中工作线线程的数目，防止因为消耗过多的内存，而把服务器累趴下(每个线程需要大约1MB内存，线程开的越多，消耗的内存也就越大，最后死机)。</li></ol><h2 id="2-3-线程池的使用"><a href="#2-3-线程池的使用" class="headerlink" title="2.3 线程池的使用"></a>2.3 线程池的使用</h2><p>Java里面线程池的顶级接口是<code>java.util.concurrent.Executor</code>，但是严格意义上讲<code>Executor</code>并不是一个线程池，而只是一个执行线程的工具。真正的线程池接口是<code>java.util.concurrent.ExecutorService</code>。</p><p>要配置一个线程池是比较复杂的，尤其是对于线程池的原理不是很清楚的情况下，很有可能配置的线程池不是较优的，因此在<code>java.util.concurrent.Executors</code>线程工厂类里面提供了一些静态工厂，生成一些常用的线程池。官方建议使用Executors工程类来创建线程池对象。</p><p>Executors类中有个创建线程池的方法如下：</p><ul><li><code>public static ExecutorService newFixedThreadPool(int nThreads)</code>：返回线程池对象。(创建的是有界线程池,也就是池中的线程个数可以指定最大数量)</li></ul><p>获取到了一个线程池ExecutorService 对象，那么怎么使用呢，在这里定义了一个使用线程池对象的方法如下：</p><ul><li><p><code>public Future&lt;?&gt; submit(Runnable task)</code>:获取线程池中的某一个线程对象，并执行</p><blockquote><p>Future接口：用来记录线程任务执行完毕后产生的结果。线程池创建与使用。</p></blockquote></li></ul><p>使用线程池中线程对象的步骤：</p><ol><li>创建线程池对象。</li><li>创建Runnable接口子类对象。(task)</li><li>提交Runnable接口子类对象。(take task)</li><li>关闭线程池(一般不做)。</li></ol><p>Runnable实现类代码：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyRunnable</span> <span class="keyword">implements</span> <span class="title">Runnable</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;我要一个教练&quot;</span>);</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Thread.sleep(<span class="number">2000</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">&quot;教练来了： &quot;</span> + Thread.currentThread().getName());</span><br><span class="line">        System.out.println(<span class="string">&quot;教我游泳,交完后，教练回到了游泳池&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>线程池测试类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ThreadPoolDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建线程池对象</span></span><br><span class="line">        ExecutorService service = Executors.newFixedThreadPool(<span class="number">2</span>);<span class="comment">//包含2个线程对象</span></span><br><span class="line">        <span class="comment">// 创建Runnable实例对象</span></span><br><span class="line">        MyRunnable r = <span class="keyword">new</span> MyRunnable();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//自己创建线程对象的方式</span></span><br><span class="line">        <span class="comment">// Thread t = new Thread(r);</span></span><br><span class="line">        <span class="comment">// t.start(); ---&gt; 调用MyRunnable中的run()</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 从线程池中获取线程对象,然后调用MyRunnable中的run()</span></span><br><span class="line">        service.submit(r);</span><br><span class="line">        <span class="comment">// 再获取个线程对象，调用MyRunnable中的run()</span></span><br><span class="line">        service.submit(r);</span><br><span class="line">        service.submit(r);</span><br><span class="line">        <span class="comment">// 注意：submit方法调用结束后，程序并不终止，是因为线程池控制了线程的关闭。</span></span><br><span class="line">        <span class="comment">// 将使用完的线程又归还到了线程池中</span></span><br><span class="line">        <span class="comment">// 关闭线程池</span></span><br><span class="line">        <span class="comment">//service.shutdown();</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第三章-Lambda表达式"><a href="#第三章-Lambda表达式" class="headerlink" title="第三章 Lambda表达式"></a>第三章 Lambda表达式</h1><h2 id="3-1-函数式编程思想概述"><a href="#3-1-函数式编程思想概述" class="headerlink" title="3.1 函数式编程思想概述"></a>3.1 函数式编程思想概述</h2><p><img src= "/img/loading.gif" data-lazy-src="img/03-Overview.png"></p><p>在数学中，<strong>函数</strong>就是有输入量、输出量的一套计算方案，也就是“拿什么东西做什么事情”。相对而言，面向对象过分强调“必须通过对象的形式来做事情”，而函数式思想则尽量忽略面向对象的复杂语法——<strong>强调做什么，而不是以什么形式做</strong>。</p><p>面向对象的思想:</p><p>​   做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情.</p><p>函数式编程思想:</p><p>​   只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程</p><h2 id="3-2-冗余的Runnable代码"><a href="#3-2-冗余的Runnable代码" class="headerlink" title="3.2 冗余的Runnable代码"></a>3.2 冗余的Runnable代码</h2><h3 id="传统写法"><a href="#传统写法" class="headerlink" title="传统写法"></a>传统写法</h3><p>当需要启动一个线程去完成任务时，通常会通过<code>java.lang.Runnable</code>接口来定义任务内容，并使用<code>java.lang.Thread</code>类来启动该线程。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01Runnable</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 匿名内部类</span></span><br><span class="line">        Runnable task = <span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123; <span class="comment">// 覆盖重写抽象方法</span></span><br><span class="line">                System.out.println(<span class="string">&quot;多线程任务执行！&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="keyword">new</span> Thread(task).start(); <span class="comment">// 启动线程</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>本着“一切皆对象”的思想，这种做法是无可厚非的：首先创建一个<code>Runnable</code>接口的匿名内部类对象来指定任务内容，再将其交给一个线程来启动。</p><h3 id="代码分析"><a href="#代码分析" class="headerlink" title="代码分析"></a>代码分析</h3><p>对于<code>Runnable</code>的匿名内部类用法，可以分析出几点内容：</p><ul><li><code>Thread</code>类需要<code>Runnable</code>接口作为参数，其中的抽象<code>run</code>方法是用来指定线程任务内容的核心；</li><li>为了指定<code>run</code>的方法体，<strong>不得不</strong>需要<code>Runnable</code>接口的实现类；</li><li>为了省去定义一个<code>RunnableImpl</code>实现类的麻烦，<strong>不得不</strong>使用匿名内部类；</li><li>必须覆盖重写抽象<code>run</code>方法，所以方法名称、方法参数、方法返回值<strong>不得不</strong>再写一遍，且不能写错；</li><li>而实际上，<strong>似乎只有方法体才是关键所在</strong>。</li></ul><h2 id="3-3-编程思想转换"><a href="#3-3-编程思想转换" class="headerlink" title="3.3 编程思想转换"></a>3.3 编程思想转换</h2><h3 id="做什么，而不是怎么做"><a href="#做什么，而不是怎么做" class="headerlink" title="做什么，而不是怎么做"></a>做什么，而不是怎么做</h3><p>我们真的希望创建一个匿名内部类对象吗？不。我们只是为了做这件事情而<strong>不得不</strong>创建一个对象。我们真正希望做的事情是：将<code>run</code>方法体内的代码传递给<code>Thread</code>类知晓。</p><p><strong>传递一段代码</strong>——这才是我们真正的目的。而创建对象只是受限于面向对象语法而不得不采取的一种手段方式。那，有没有更加简单的办法？如果我们将关注点从“怎么做”回归到“做什么”的本质上，就会发现只要能够更好地达到目的，过程与形式其实并不重要。</p><h3 id="生活举例"><a href="#生活举例" class="headerlink" title="生活举例"></a>生活举例</h3><p><img src= "/img/loading.gif" data-lazy-src="img/01-%E4%BA%A4%E9%80%9A%E6%96%B9%E5%BC%8F.png"></p><p>当我们需要从北京到上海时，可以选择高铁、汽车、骑行或是徒步。我们的真正目的是到达上海，而如何才能到达上海的形式并不重要，所以我们一直在探索有没有比高铁更好的方式——搭乘飞机。</p><p><img src= "/img/loading.gif" data-lazy-src="img/02-Lambda.png"></p><p>而现在这种飞机（甚至是飞船）已经诞生：2014年3月Oracle所发布的Java 8（JDK 1.8）中，加入了<strong>Lambda表达式</strong>的重量级新特性，为我们打开了新世界的大门。</p><h2 id="3-4-体验Lambda的更优写法"><a href="#3-4-体验Lambda的更优写法" class="headerlink" title="3.4 体验Lambda的更优写法"></a>3.4 体验Lambda的更优写法</h2><p>借助Java 8的全新语法，上述<code>Runnable</code>接口的匿名内部类写法可以通过更简单的Lambda表达式达到等效：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo02LambdaRunnable</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; System.out.println(<span class="string">&quot;多线程任务执行！&quot;</span>)).start(); <span class="comment">// 启动线程</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这段代码和刚才的执行效果是完全一样的，可以在1.8或更高的编译级别下通过。从代码的语义中可以看出：我们启动了一个线程，而线程任务的内容以一种更加简洁的形式被指定。</p><p>不再有“不得不创建接口对象”的束缚，不再有“抽象方法覆盖重写”的负担，就是这么简单！</p><h2 id="3-5-回顾匿名内部类"><a href="#3-5-回顾匿名内部类" class="headerlink" title="3.5 回顾匿名内部类"></a>3.5 回顾匿名内部类</h2><p>Lambda是怎样击败面向对象的？在上例中，核心代码其实只是如下所示的内容：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">() -&gt; System.out.println(<span class="string">&quot;多线程任务执行！&quot;</span>)</span><br></pre></td></tr></table></figure><p>为了理解Lambda的语义，我们需要从传统的代码起步。</p><h3 id="使用实现类"><a href="#使用实现类" class="headerlink" title="使用实现类"></a>使用实现类</h3><p>要启动一个线程，需要创建一个<code>Thread</code>类的对象并调用<code>start</code>方法。而为了指定线程执行的内容，需要调用<code>Thread</code>类的构造方法：</p><ul><li><code>public Thread(Runnable target)</code></li></ul><p>为了获取<code>Runnable</code>接口的实现对象，可以为该接口定义一个实现类<code>RunnableImpl</code>：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RunnableImpl</span> <span class="keyword">implements</span> <span class="title">Runnable</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;多线程任务执行！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后创建该实现类的对象作为<code>Thread</code>类的构造参数：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo03ThreadInitParam</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Runnable task = <span class="keyword">new</span> RunnableImpl();</span><br><span class="line">        <span class="keyword">new</span> Thread(task).start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="使用匿名内部类"><a href="#使用匿名内部类" class="headerlink" title="使用匿名内部类"></a>使用匿名内部类</h3><p>这个<code>RunnableImpl</code>类只是为了实现<code>Runnable</code>接口而存在的，而且仅被使用了唯一一次，所以使用匿名内部类的语法即可省去该类的单独定义，即匿名内部类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo04ThreadNameless</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;多线程任务执行！&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;).start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="匿名内部类的好处与弊端"><a href="#匿名内部类的好处与弊端" class="headerlink" title="匿名内部类的好处与弊端"></a>匿名内部类的好处与弊端</h3><p>一方面，匿名内部类可以帮我们<strong>省去实现类的定义</strong>；另一方面，匿名内部类的语法——<strong>确实太复杂了！</strong></p><h3 id="语义分析"><a href="#语义分析" class="headerlink" title="语义分析"></a>语义分析</h3><p>仔细分析该代码中的语义，<code>Runnable</code>接口只有一个<code>run</code>方法的定义：</p><ul><li><code>public abstract void run();</code></li></ul><p>即制定了一种做事情的方案（其实就是一个函数）：</p><ul><li><strong>无参数</strong>：不需要任何条件即可执行该方案。</li><li><strong>无返回值</strong>：该方案不产生任何结果。</li><li><strong>代码块</strong>（方法体）：该方案的具体执行步骤。</li></ul><p>同样的语义体现在<code>Lambda</code>语法中，要更加简单：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">() -&gt; System.out.println(<span class="string">&quot;多线程任务执行！&quot;</span>)</span><br></pre></td></tr></table></figure><ul><li>前面的一对小括号即<code>run</code>方法的参数（无），代表不需要任何条件；</li><li>中间的一个箭头代表将前面的参数传递给后面的代码；</li><li>后面的输出语句即业务逻辑代码。</li></ul><h2 id="3-6-Lambda标准格式"><a href="#3-6-Lambda标准格式" class="headerlink" title="3.6 Lambda标准格式"></a>3.6 Lambda标准格式</h2><p>Lambda省去面向对象的条条框框，格式由<strong>3个部分</strong>组成：</p><ul><li>一些参数</li><li>一个箭头</li><li>一段代码</li></ul><p>Lambda表达式的<strong>标准格式</strong>为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(参数类型 参数名称) -&gt; &#123; 代码语句 &#125;</span><br></pre></td></tr></table></figure><p>格式说明：</p><ul><li>小括号内的语法与传统方法参数列表一致：无参数则留空；多个参数则用逗号分隔。</li><li><code>-&gt;</code>是新引入的语法格式，代表指向动作。</li><li>大括号内的语法与传统方法体要求基本一致。</li></ul><h2 id="3-7-练习：使用Lambda标准格式（无参无返回）"><a href="#3-7-练习：使用Lambda标准格式（无参无返回）" class="headerlink" title="3.7 练习：使用Lambda标准格式（无参无返回）"></a>3.7 练习：使用Lambda标准格式（无参无返回）</h2><h3 id="题目"><a href="#题目" class="headerlink" title="题目"></a>题目</h3><p>给定一个厨子<code>Cook</code>接口，内含唯一的抽象方法<code>makeFood</code>，且无参数、无返回值。如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Cook</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">makeFood</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在下面的代码中，请使用Lambda的<strong>标准格式</strong>调用<code>invokeCook</code>方法，打印输出“吃饭啦！”字样：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo05InvokeCook</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// TODO 请在此使用Lambda【标准格式】调用invokeCook方法</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">invokeCook</span><span class="params">(Cook cook)</span> </span>&#123;</span><br><span class="line">        cook.makeFood();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="解答"><a href="#解答" class="headerlink" title="解答"></a>解答</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    invokeCook(() -&gt; &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;吃饭啦！&quot;</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>备注：小括号代表<code>Cook</code>接口<code>makeFood</code>抽象方法的参数为空，大括号代表<code>makeFood</code>的方法体。</p></blockquote><h2 id="3-8-Lambda的参数和返回值"><a href="#3-8-Lambda的参数和返回值" class="headerlink" title="3.8 Lambda的参数和返回值"></a>3.8 Lambda的参数和返回值</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">需求:</span><br><span class="line">    使用数组存储多个Person对象</span><br><span class="line">    对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序</span><br></pre></td></tr></table></figure><p>下面举例演示<code>java.util.Comparator&lt;T&gt;</code>接口的使用场景代码，其中的抽象方法定义为：</p><ul><li><code>public abstract int compare(T o1, T o2);</code></li></ul><p>当需要对一个对象数组进行排序时，<code>Arrays.sort</code>方法需要一个<code>Comparator</code>接口实例来指定排序的规则。假设有一个<code>Person</code>类，含有<code>String name</code>和<code>int age</code>两个成员变量：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123; </span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 省略构造器、toString方法与Getter Setter </span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="传统写法-1"><a href="#传统写法-1" class="headerlink" title="传统写法"></a>传统写法</h3><p>如果使用传统的代码对<code>Person[]</code>数组进行排序，写法如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"><span class="keyword">import</span> java.util.Comparator;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo06Comparator</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 本来年龄乱序的对象数组</span></span><br><span class="line">        Person[] array = &#123;</span><br><span class="line">            <span class="keyword">new</span> Person(<span class="string">&quot;古力娜扎&quot;</span>, <span class="number">19</span>),</span><br><span class="line">            <span class="keyword">new</span> Person(<span class="string">&quot;迪丽热巴&quot;</span>, <span class="number">18</span>),</span><br><span class="line">            <span class="keyword">new</span> Person(<span class="string">&quot;马尔扎哈&quot;</span>, <span class="number">20</span>) &#125;;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 匿名内部类</span></span><br><span class="line">        Comparator&lt;Person&gt; comp = <span class="keyword">new</span> Comparator&lt;Person&gt;() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(Person o1, Person o2)</span> </span>&#123;</span><br><span class="line">                <span class="keyword">return</span> o1.getAge() - o2.getAge();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        Arrays.sort(array, comp); <span class="comment">// 第二个参数为排序规则，即Comparator接口实例</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (Person person : array) &#123;</span><br><span class="line">            System.out.println(person);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这种做法在面向对象的思想中，似乎也是“理所当然”的。其中<code>Comparator</code>接口的实例（使用了匿名内部类）代表了“按照年龄从小到大”的排序规则。</p><h3 id="代码分析-1"><a href="#代码分析-1" class="headerlink" title="代码分析"></a>代码分析</h3><p>下面我们来搞清楚上述代码真正要做什么事情。</p><ul><li>为了排序，<code>Arrays.sort</code>方法需要排序规则，即<code>Comparator</code>接口的实例，抽象方法<code>compare</code>是关键；</li><li>为了指定<code>compare</code>的方法体，<strong>不得不</strong>需要<code>Comparator</code>接口的实现类；</li><li>为了省去定义一个<code>ComparatorImpl</code>实现类的麻烦，<strong>不得不</strong>使用匿名内部类；</li><li>必须覆盖重写抽象<code>compare</code>方法，所以方法名称、方法参数、方法返回值<strong>不得不</strong>再写一遍，且不能写错；</li><li>实际上，<strong>只有参数和方法体才是关键</strong>。</li></ul><h3 id="Lambda写法"><a href="#Lambda写法" class="headerlink" title="Lambda写法"></a>Lambda写法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo07ComparatorLambda</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Person[] array = &#123;</span><br><span class="line">            <span class="keyword">new</span> Person(<span class="string">&quot;古力娜扎&quot;</span>, <span class="number">19</span>),</span><br><span class="line">            <span class="keyword">new</span> Person(<span class="string">&quot;迪丽热巴&quot;</span>, <span class="number">18</span>),</span><br><span class="line">            <span class="keyword">new</span> Person(<span class="string">&quot;马尔扎哈&quot;</span>, <span class="number">20</span>) &#125;;</span><br><span class="line"></span><br><span class="line">        Arrays.sort(array, (Person a, Person b) -&gt; &#123;</span><br><span class="line">            <span class="keyword">return</span> a.getAge() - b.getAge();</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (Person person : array) &#123;</span><br><span class="line">            System.out.println(person);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-9-练习：使用Lambda标准格式（有参有返回）"><a href="#3-9-练习：使用Lambda标准格式（有参有返回）" class="headerlink" title="3.9 练习：使用Lambda标准格式（有参有返回）"></a>3.9 练习：使用Lambda标准格式（有参有返回）</h2><h3 id="题目-1"><a href="#题目-1" class="headerlink" title="题目"></a>题目</h3><p>给定一个计算器<code>Calculator</code>接口，内含抽象方法<code>calc</code>可以将两个int数字相加得到和值：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Calculator</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">calc</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在下面的代码中，请使用Lambda的<strong>标准格式</strong>调用<code>invokeCalc</code>方法，完成120和130的相加计算：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo08InvokeCalc</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// TODO 请在此使用Lambda【标准格式】调用invokeCalc方法来计算120+130的结果ß</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">invokeCalc</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b, Calculator calculator)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> result = calculator.calc(a, b);</span><br><span class="line">        System.out.println(<span class="string">&quot;结果是：&quot;</span> + result);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="解答-1"><a href="#解答-1" class="headerlink" title="解答"></a>解答</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    invokeCalc(<span class="number">120</span>, <span class="number">130</span>, (<span class="keyword">int</span> a, <span class="keyword">int</span> b) -&gt; &#123;</span><br><span class="line">        <span class="keyword">return</span> a + b;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>备注：小括号代表<code>Calculator</code>接口<code>calc</code>抽象方法的参数，大括号代表<code>calc</code>的方法体。</p></blockquote><h2 id="3-10-Lambda省略格式"><a href="#3-10-Lambda省略格式" class="headerlink" title="3.10 Lambda省略格式"></a>3.10 Lambda省略格式</h2><h3 id="可推导即可省略"><a href="#可推导即可省略" class="headerlink" title="可推导即可省略"></a>可推导即可省略</h3><p>Lambda强调的是“做什么”而不是“怎么做”，所以凡是可以根据上下文推导得知的信息，都可以省略。例如上例还可以使用Lambda的省略写法：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    invokeCalc(<span class="number">120</span>, <span class="number">130</span>, (a, b) -&gt; a + b);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="省略规则"><a href="#省略规则" class="headerlink" title="省略规则"></a>省略规则</h3><p>在Lambda标准格式的基础上，使用省略写法的规则为：</p><ol><li>小括号内参数的类型可以省略；</li><li>如果小括号内<strong>有且仅有一个参</strong>，则小括号可以省略；</li><li>如果大括号内<strong>有且仅有一个语句</strong>，则无论是否有返回值，都可以省略大括号、return关键字及语句分号。</li></ol><blockquote><p>备注：掌握这些省略规则后，请对应地回顾本章开头的多线程案例。</p></blockquote><h2 id="3-11-练习：使用Lambda省略格式"><a href="#3-11-练习：使用Lambda省略格式" class="headerlink" title="3.11 练习：使用Lambda省略格式"></a>3.11 练习：使用Lambda省略格式</h2><h3 id="题目-2"><a href="#题目-2" class="headerlink" title="题目"></a>题目</h3><p>仍然使用前文含有唯一<code>makeFood</code>抽象方法的厨子<code>Cook</code>接口，在下面的代码中，请使用Lambda的<strong>省略格式</strong>调用<code>invokeCook</code>方法，打印输出“吃饭啦！”字样：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo09InvokeCook</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// TODO 请在此使用Lambda【省略格式】调用invokeCook方法</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">invokeCook</span><span class="params">(Cook cook)</span> </span>&#123;</span><br><span class="line">        cook.makeFood();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="解答-2"><a href="#解答-2" class="headerlink" title="解答"></a>解答</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    invokeCook(() -&gt; System.out.println(<span class="string">&quot;吃饭啦！&quot;</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-12-Lambda的使用前提"><a href="#3-12-Lambda的使用前提" class="headerlink" title="3.12 Lambda的使用前提"></a>3.12 Lambda的使用前提</h2><p>Lambda的语法非常简洁，完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意：</p><ol><li>使用Lambda必须具有接口，且要求<strong>接口中有且仅有一个抽象方法</strong>。<br>无论是JDK内置的<code>Runnable</code>、<code>Comparator</code>接口还是自定义的接口，只有当接口中的抽象方法存在且唯一时，才可以使用Lambda。</li><li>使用Lambda必须具有<strong>上下文推断</strong>。<br>也就是方法的参数或局部变量类型必须为Lambda对应的接口类型，才能使用Lambda作为该接口的实例。</li></ol><blockquote><p>备注：有且仅有一个抽象方法的接口，称为“<strong>函数式接口</strong>”。</p></blockquote>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记10-Map集合</title>
      <link href="java/javase/note/note10/"/>
      <url>java/javase/note/note10/</url>
      
        <content type="html"><![CDATA[<h3 id="Map集合"><a href="#Map集合" class="headerlink" title="Map集合"></a>Map集合</h3><p>Map集合就是python中的dict</p><h3 id="Map集合的定义-声明"><a href="#Map集合的定义-声明" class="headerlink" title="Map集合的定义(声明)"></a>Map集合的定义(声明)</h3><p>Map&lt;key的泛型, 值的泛型&gt; 变量名 = new HashMap&lt;key的泛型, 值的泛型&gt;();</p><p>例如</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Map&lt;Integer, String&gt; m1 = <span class="keyword">new</span> HashMap&lt;Integer, String&gt;();</span><br></pre></td></tr></table></figure><h3 id="增加和修改操作"><a href="#增加和修改操作" class="headerlink" title="增加和修改操作"></a>增加和修改操作</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Object.put(<span class="keyword">new</span> key, <span class="keyword">new</span> value);</span><br><span class="line"><span class="comment">// 如果没有就是增加,有就是修改</span></span><br><span class="line"><span class="comment">// 返回值为原来的那个value的值,没有就返回null</span></span><br></pre></td></tr></table></figure><h3 id="查找操作"><a href="#查找操作" class="headerlink" title="查找操作"></a>查找操作</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Object.get(Object key)</span><br><span class="line"><span class="comment">// 如果不存在,返回null</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="判断存在操作"><a href="#判断存在操作" class="headerlink" title="判断存在操作"></a>判断存在操作</h3><p>判断建存在</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Object.containsKey(<span class="number">1</span>)</span><br><span class="line"><span class="comment">// 返回布尔类型</span></span><br></pre></td></tr></table></figure><p>判断值存在</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Object.containsValue(<span class="string">&quot;one&quot;</span>)</span><br><span class="line"><span class="comment">// 返回布尔类型</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记11-【异常、线程】</title>
      <link href="java/javase/note/note11/"/>
      <url>java/javase/note/note11/</url>
      
        <content type="html"><![CDATA[<h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li>异常、线程</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><ul><li><input checked="" disabled="" type="checkbox"> 能够辨别程序中异常和错误的区别</li><li><input checked="" disabled="" type="checkbox"> 说出异常的分类</li><li><input disabled="" type="checkbox"> 说出虚拟机处理异常的方式</li><li><input disabled="" type="checkbox"> 列举出常见的三个运行期异常</li><li><input checked="" disabled="" type="checkbox"> 能够使用try…catch关键字处理异常</li><li><input disabled="" type="checkbox"> 能够使用throws关键字处理异常</li><li><input disabled="" type="checkbox"> 能够自定义异常类</li><li><input disabled="" type="checkbox"> 能够处理自定义异常类</li><li><input disabled="" type="checkbox"> 说出进程的概念</li><li><input disabled="" type="checkbox"> 说出线程的概念</li><li><input disabled="" type="checkbox"> 能够理解并发与并行的区别</li><li><input disabled="" type="checkbox"> 能够开启新线程</li></ul><h1 id="第一章-异常"><a href="#第一章-异常" class="headerlink" title="第一章    异常"></a>第一章    异常</h1><h2 id="1-1-异常概念"><a href="#1-1-异常概念" class="headerlink" title="1.1 异常概念"></a>1.1 异常概念</h2><p>异常，就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是：</p><ul><li><strong>异常</strong> ：指的是程序在执行过程中，出现的非正常的情况，最终会导致JVM的非正常停止。</li></ul><p>在Java等面向对象的编程语言中，异常本身是一个类，产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。</p><blockquote><p>异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行.</p></blockquote><h2 id="1-2-异常体系"><a href="#1-2-异常体系" class="headerlink" title="1.2 异常体系"></a>1.2 异常体系</h2><p>异常机制其实是帮助我们<strong>找到</strong>程序中的问题，异常的根类是<code>java.lang.Throwable</code>，其下有两个子类：<code>java.lang.Error</code>与<code>java.lang.Exception</code>，平常所说的异常指<code>java.lang.Exception</code>。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E5%BC%82%E5%B8%B8%E4%BD%93%E7%B3%BB.png"></p><p><strong>Throwable体系：</strong></p><ul><li><strong>Error</strong>:严重错误Error，无法通过处理的错误，只能事先避免，好比绝症。</li><li><strong>Exception</strong>:表示异常，异常产生后程序员可以通过代码的方式纠正，使程序继续运行，是必须要处理的。好比感冒、阑尾炎。</li></ul><p><strong>Throwable中的常用方法：</strong></p><ul><li><p><code>public void printStackTrace()</code>:打印异常的详细信息。</p><p><em>包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。</em></p></li><li><p><code>public String getMessage()</code>:获取发生异常的原因。</p><p><em>提示给用户的时候,就提示错误原因。</em></p></li><li><p><code>public String toString()</code>:获取异常的类型和异常描述信息(不用)。</p></li></ul><p><em><strong>出现异常,不要紧张,把异常的简单类名,拷贝到API中去查。</strong></em></p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E7%AE%80%E5%8D%95%E7%9A%84%E5%BC%82%E5%B8%B8%E6%9F%A5%E7%9C%8B.bmp"></p><h2 id="1-3-异常分类"><a href="#1-3-异常分类" class="headerlink" title="1.3 异常分类"></a>1.3 异常分类</h2><p>我们平常说的异常就是指Exception，因为这类异常一旦出现，我们就要对代码进行更正，修复程序。</p><p><strong>异常(Exception)的分类</strong>:根据在编译时期还是运行时期去检查异常?</p><ul><li><strong>编译时期异常</strong>:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)</li><li><strong>运行时期异常</strong>:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)</li></ul><p>​    <img src= "/img/loading.gif" data-lazy-src="img%5C%E5%BC%82%E5%B8%B8%E7%9A%84%E5%88%86%E7%B1%BB.png"></p><h2 id="1-4-异常的产生过程解析"><a href="#1-4-异常的产生过程解析" class="headerlink" title="1.4     异常的产生过程解析"></a>1.4     异常的产生过程解析</h2><p>先运行下面的程序，程序会产生一个数组索引越界异常ArrayIndexOfBoundsException。我们通过图解来解析下异常产生的过程。</p><p> 工具类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ArrayTools</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 对给定的数组通过给定的角标获取元素。</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getElement</span><span class="params">(<span class="keyword">int</span>[] arr, <span class="keyword">int</span> index)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> element = arr[index];</span><br><span class="line">        <span class="keyword">return</span> element;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p> 测试类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ExceptionDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] arr = &#123; <span class="number">34</span>, <span class="number">12</span>, <span class="number">67</span> &#125;;</span><br><span class="line">        intnum = ArrayTools.getElement(arr, <span class="number">4</span>)</span><br><span class="line">        System.out.println(<span class="string">&quot;num=&quot;</span> + num);</span><br><span class="line">        System.out.println(<span class="string">&quot;over&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上述程序执行过程图解：</p><p> <img src= "/img/loading.gif" data-lazy-src="img%5C%E5%BC%82%E5%B8%B8%E4%BA%A7%E7%94%9F%E8%BF%87%E7%A8%8B.png"></p><h1 id="第二章-异常的处理"><a href="#第二章-异常的处理" class="headerlink" title="第二章 异常的处理"></a>第二章 异常的处理</h1><p>Java异常处理的五个关键字：<strong>try、catch、finally、throw、throws</strong></p><h2 id="2-1-抛出异常throw"><a href="#2-1-抛出异常throw" class="headerlink" title="2.1  抛出异常throw"></a>2.1  抛出异常throw</h2><p>在编写程序时，我们必须要考虑程序出现问题的情况。比如，在定义方法时，方法需要接受参数。那么，当调用方法使用接受到的参数时，首先需要先对参数数据进行合法的判断，数据若不合法，就应该告诉调用者，传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。</p><p>在java中，提供了一个<strong>throw</strong>关键字，它用来抛出一个指定的异常对象。那么，抛出一个异常具体如何操作呢？</p><ol><li><p>创建一个异常对象。封装一些提示信息(信息可以自己编写)。</p></li><li><p>需要将这个异常对象告知给调用者。怎么告知呢？怎么将这个异常对象传递到调用者处呢？通过关键字throw就可以完成。throw 异常对象。</p><p>throw<strong>用在方法内</strong>，用来抛出一个异常对象，将这个异常对象传递到调用者处，并结束当前方法的执行。</p></li></ol><p><strong>使用格式：</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">throw new 异常类名(参数);</span><br></pre></td></tr></table></figure><p> 例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException(<span class="string">&quot;要访问的arr数组不存在&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">throw</span> <span class="keyword">new</span> ArrayIndexOutOfBoundsException(<span class="string">&quot;该索引在数组中不存在，已超出范围&quot;</span>);</span><br></pre></td></tr></table></figure><p>学习完抛出异常的格式后，我们通过下面程序演示下throw的使用。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ThrowDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//创建一个数组 </span></span><br><span class="line">        <span class="keyword">int</span>[] arr = &#123;<span class="number">2</span>,<span class="number">4</span>,<span class="number">52</span>,<span class="number">2</span>&#125;;</span><br><span class="line">        <span class="comment">//根据索引找对应的元素 </span></span><br><span class="line">        <span class="keyword">int</span> index = <span class="number">4</span>;</span><br><span class="line">        <span class="keyword">int</span> element = getElement(arr, index);</span><br><span class="line"></span><br><span class="line">        System.out.println(element);</span><br><span class="line">        System.out.println(<span class="string">&quot;over&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 根据 索引找到数组中对应的元素</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getElement</span><span class="params">(<span class="keyword">int</span>[] arr,<span class="keyword">int</span> index)</span></span>&#123; </span><br><span class="line">        <span class="comment">//判断  索引是否越界</span></span><br><span class="line">        <span class="keyword">if</span>(index&lt;<span class="number">0</span> || index&gt;arr.length-<span class="number">1</span>)&#123;</span><br><span class="line">             <span class="comment">/*</span></span><br><span class="line"><span class="comment">             判断条件如果满足，当执行完throw抛出异常对象后，方法已经无法继续运算。</span></span><br><span class="line"><span class="comment">             这时就会结束当前方法的执行，并将异常告知给调用者。这时就需要通过异常来解决。 </span></span><br><span class="line"><span class="comment">              */</span></span><br><span class="line">             <span class="keyword">throw</span> <span class="keyword">new</span> ArrayIndexOutOfBoundsException(<span class="string">&quot;哥们，角标越界了~~~&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> element = arr[index];</span><br><span class="line">        <span class="keyword">return</span> element;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注意：如果产生了问题，我们就会throw将问题描述类即异常进行抛出，也就是将问题返回给该方法的调用者。</p><p>那么对于调用者来说，该怎么处理呢？一种是进行捕获处理，另一种就是继续讲问题声明出去，使用throws声明处理。</p></blockquote><h2 id="2-2-Objects非空判断"><a href="#2-2-Objects非空判断" class="headerlink" title="2.2 Objects非空判断"></a>2.2 Objects非空判断</h2><p>还记得我们学习过一个类Objects吗，曾经提到过它由一些静态的实用方法组成，这些方法是null-save（空指针安全的）或null-tolerant（容忍空指针的），那么在它的源码中，对对象为null的值进行了抛出异常操作。</p><ul><li><code>public static &lt;T&gt; T requireNonNull(T obj)</code>:查看指定引用对象不是null。</li></ul><p>查看源码发现这里对为null的进行了抛出异常操作：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="function">T <span class="title">requireNonNull</span><span class="params">(T obj)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (obj == <span class="keyword">null</span>)</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">    <span class="keyword">return</span> obj;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="2-3-声明异常throws"><a href="#2-3-声明异常throws" class="headerlink" title="2.3  声明异常throws"></a>2.3  声明异常throws</h2><p><strong>声明异常</strong>：将问题标识出来，报告给调用者。如果方法内通过throw抛出了编译时异常，而没有捕获处理（稍后讲解该方式），那么必须通过throws进行声明，让调用者去处理。</p><p>关键字<strong>throws</strong>运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).</p><p><strong>声明异常格式：</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…&#123;   &#125;  </span><br></pre></td></tr></table></figure><p>声明异常的代码演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ThrowsDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        read(<span class="string">&quot;a.txt&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">read</span><span class="params">(String path)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (!path.equals(<span class="string">&quot;a.txt&quot;</span>)) &#123;<span class="comment">//如果不是 a.txt这个文件 </span></span><br><span class="line">            <span class="comment">// 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw</span></span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> FileNotFoundException(<span class="string">&quot;文件不存在&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>throws用于进行异常类的声明，若该方法可能有多种异常情况产生，那么在throws后面可以写多个异常类，用逗号隔开。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ThrowsDemo2</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        read(<span class="string">&quot;a.txt&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">read</span><span class="params">(String path)</span><span class="keyword">throws</span> FileNotFoundException, IOException </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (!path.equals(<span class="string">&quot;a.txt&quot;</span>)) &#123;<span class="comment">//如果不是 a.txt这个文件 </span></span><br><span class="line">            <span class="comment">// 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw</span></span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> FileNotFoundException(<span class="string">&quot;文件不存在&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (!path.equals(<span class="string">&quot;b.txt&quot;</span>)) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IOException();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="2-4-捕获异常try…catch"><a href="#2-4-捕获异常try…catch" class="headerlink" title="2.4  捕获异常try…catch"></a>2.4  捕获异常try…catch</h2><p>如果异常出现的话,会立刻终止程序,所以我们得处理异常:</p><ol><li>该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。</li><li>在方法中使用try-catch的语句块来处理异常。</li></ol><p><strong>try-catch</strong>的方式就是捕获异常。</p><ul><li><strong>捕获异常</strong>：Java中对异常有针对性的语句进行捕获，可以对出现的异常进行指定方式的处理。</li></ul><p>捕获异常语法如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span>&#123;</span><br><span class="line">     编写可能会出现异常的代码</span><br><span class="line">&#125;<span class="keyword">catch</span>(异常类型  e)&#123;</span><br><span class="line">     处理异常的代码</span><br><span class="line">     <span class="comment">//记录日志/打印异常信息/继续抛出异常</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>try：</strong>该代码块中编写可能产生异常的代码。</p><p><strong>catch：</strong>用来进行某种异常的捕获，实现对捕获到的异常进行处理。</p><blockquote><p>注意:try和catch都不能单独使用,必须连用。</p></blockquote><p>演示如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TryCatchDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;<span class="comment">// 当产生异常时，必须有处理方式。要么捕获，要么声明。</span></span><br><span class="line">            read(<span class="string">&quot;b.txt&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (FileNotFoundException e) &#123;<span class="comment">// 括号中需要定义什么呢？</span></span><br><span class="line">            <span class="comment">//try中抛出的是什么异常，在括号中就定义什么异常类型</span></span><br><span class="line">            System.out.println(e);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">&quot;over&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 我们 当前的这个方法中 有异常  有编译期异常</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">read</span><span class="params">(String path)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (!path.equals(<span class="string">&quot;a.txt&quot;</span>)) &#123;<span class="comment">//如果不是 a.txt这个文件 </span></span><br><span class="line">            <span class="comment">// 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw</span></span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> FileNotFoundException(<span class="string">&quot;文件不存在&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如何获取异常信息：</p><p>Throwable类中定义了一些查看方法:</p><ul><li><code>public String getMessage()</code>:获取异常的描述信息,原因(提示给用户的时候,就提示错误原因。</li></ul><ul><li><code>public String toString()</code>:获取异常的类型和异常描述信息(不用)。</li><li><code>public void printStackTrace()</code>:打印异常的跟踪栈信息并输出到控制台。</li></ul><p>​            <em>包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。</em></p><h2 id="2-4-finally-代码块"><a href="#2-4-finally-代码块" class="headerlink" title="2.4 finally 代码块"></a>2.4 finally 代码块</h2><p><strong>finally</strong>：有一些特定的代码无论异常是否发生，都需要执行。另外，因为异常会引发程序跳转，导致有些语句执行不到。而finally就是解决这个问题的，在finally代码块中存放的代码都是一定会被执行的。</p><p>什么时候的代码必须最终执行？</p><p>当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。</p><p>finally的语法:</p><p> try…catch….finally:自身需要处理异常,最终还得关闭资源。</p><blockquote><p>注意:finally不能单独使用。</p></blockquote><p>比如在我们之后学习的IO流中，当打开了一个关联文件的资源，最后程序不管结果如何，都需要把这个资源关闭掉。</p><p>finally代码参考如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TryCatchDemo4</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            read(<span class="string">&quot;a.txt&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (FileNotFoundException e) &#123;</span><br><span class="line">            <span class="comment">//抓取到的是编译期异常  抛出去的是运行期 </span></span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(e);</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;不管程序怎样，这里都将会被执行。&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">&quot;over&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 我们 当前的这个方法中 有异常  有编译期异常</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">read</span><span class="params">(String path)</span> <span class="keyword">throws</span> FileNotFoundException </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (!path.equals(<span class="string">&quot;a.txt&quot;</span>)) &#123;<span class="comment">//如果不是 a.txt这个文件 </span></span><br><span class="line">            <span class="comment">// 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw</span></span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> FileNotFoundException(<span class="string">&quot;文件不存在&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。</p></blockquote><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E6%AD%BB%E4%BA%86%E9%83%BD%E8%A6%81try.bmp"></p><h2 id="2-5-异常注意事项"><a href="#2-5-异常注意事项" class="headerlink" title="2.5   异常注意事项"></a>2.5   异常注意事项</h2><ul><li><p>多个异常使用捕获又该如何处理呢？</p><ol><li>多个异常分别处理。</li><li>多个异常一次捕获，多次处理。</li><li>多个异常一次捕获一次处理。</li></ol><p>一般我们是使用一次捕获多次处理方式，格式如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span>&#123;</span><br><span class="line">     编写可能会出现异常的代码</span><br><span class="line">&#125;<span class="keyword">catch</span>(异常类型A  e)&#123;  当<span class="keyword">try</span>中出现A类型异常,就用该<span class="keyword">catch</span>来捕获.</span><br><span class="line">     处理异常的代码</span><br><span class="line">     <span class="comment">//记录日志/打印异常信息/继续抛出异常</span></span><br><span class="line">&#125;<span class="keyword">catch</span>(异常类型B  e)&#123;  当<span class="keyword">try</span>中出现B类型异常,就用该<span class="keyword">catch</span>来捕获.</span><br><span class="line">     处理异常的代码</span><br><span class="line">     <span class="comment">//记录日志/打印异常信息/继续抛出异常</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注意:这种异常处理方式，要求多个catch中的异常不能相同，并且若catch中的多个异常之间有子父类异常的关系，那么子类异常要求在上面的catch处理，父类异常在下面的catch处理。</p></blockquote></li><li><p>运行时异常被抛出可以不处理。即不捕获也不声明抛出。</p></li><li><p>如果finally有return语句,永远返回finally中的结果,避免该情况. </p></li><li><p>如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。</p></li><li><p>父类方法没有抛出异常，子类重写父类该方法时也不可抛出异常。此时子类产生该异常，只能捕获处理，不能声明抛出</p></li></ul><h1 id="第三章-自定义异常"><a href="#第三章-自定义异常" class="headerlink" title="第三章 自定义异常"></a>第三章 自定义异常</h1><h2 id="3-1-概述"><a href="#3-1-概述" class="headerlink" title="3.1 概述"></a>3.1 概述</h2><p><strong>为什么需要自定义异常类:</strong></p><p>我们说了Java中不同的异常类,分别表示着某一种具体的异常情况,那么在开发中总是有些异常情况是SUN没有定义好的,此时我们根据自己业务的异常情况来定义异常类。例如年龄负数问题,考试成绩负数问题等等。</p><p>在上述代码中，发现这些异常都是JDK内部定义好的，但是实际开发中也会出现很多异常,这些异常很可能在JDK中没有定义过,例如年龄负数问题,考试成绩负数问题.那么能不能自己定义异常呢？</p><p><strong>什么是自定义异常类:</strong></p><p>在开发中根据自己业务的异常情况来定义异常类.</p><p>自定义一个业务逻辑异常: <strong>RegisterException</strong>。一个注册异常类。</p><p><strong>异常类如何定义:</strong></p><ol><li>自定义一个编译期异常: 自定义类 并继承于<code>java.lang.Exception</code>。</li><li>自定义一个运行时期的异常类:自定义类 并继承于<code>java.lang.RuntimeException</code>。</li></ol><h2 id="3-2-自定义异常的练习"><a href="#3-2-自定义异常的练习" class="headerlink" title="3.2 自定义异常的练习"></a>3.2 自定义异常的练习</h2><p>要求：我们模拟注册操作，如果用户名已存在，则抛出异常并提示：亲，该用户名已经被注册。</p><p>首先定义一个登陆异常类RegisterException：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 业务逻辑异常</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RegisterException</span> <span class="keyword">extends</span> <span class="title">Exception</span> </span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 空参构造</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">RegisterException</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> message 表示异常提示</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">RegisterException</span><span class="params">(String message)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>模拟登陆操作，使用数组模拟数据库中存储的数据，并提供当前注册账号是否存在方法用于判断。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 模拟数据库中已存在账号</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String[] names = &#123;<span class="string">&quot;bill&quot;</span>,<span class="string">&quot;hill&quot;</span>,<span class="string">&quot;jill&quot;</span>&#125;;</span><br><span class="line">   </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;     </span><br><span class="line">        <span class="comment">//调用方法</span></span><br><span class="line">        <span class="keyword">try</span>&#123;</span><br><span class="line">              <span class="comment">// 可能出现异常的代码</span></span><br><span class="line">            checkUsername(<span class="string">&quot;nill&quot;</span>);</span><br><span class="line">            System.out.println(<span class="string">&quot;注册成功&quot;</span>);<span class="comment">//如果没有异常就是注册成功</span></span><br><span class="line">        &#125;<span class="keyword">catch</span>(RegisterException e)&#123;</span><br><span class="line">            <span class="comment">//处理异常</span></span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//判断当前注册账号是否存在</span></span><br><span class="line">    <span class="comment">//因为是编译期异常，又想调用者去处理 所以声明该异常</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">checkUsername</span><span class="params">(String uname)</span> <span class="keyword">throws</span> LoginException</span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (String name : names) &#123;</span><br><span class="line">            <span class="keyword">if</span>(name.equals(uname))&#123;<span class="comment">//如果名字在这里面 就抛出登陆异常</span></span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> RegisterException(<span class="string">&quot;亲&quot;</span>+name+<span class="string">&quot;已经被注册了！&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第四章-多线程"><a href="#第四章-多线程" class="headerlink" title="第四章 多线程"></a>第四章 多线程</h1><p>我们在之前，学习的程序在没有跳转语句的前提下，都是由上至下依次执行，那现在想要设计一个程序，边打游戏边听歌，怎么设计？</p><p>要解决上述问题,咱们得使用多进程或者多线程来解决.</p><h2 id="4-1-并发与并行"><a href="#4-1-并发与并行" class="headerlink" title="4.1 并发与并行"></a>4.1 并发与并行</h2><ul><li><strong>并发</strong>：指两个或多个事件在<strong>同一个时间段内</strong>发生。</li><li><strong>并行</strong>：指两个或多个事件在<strong>同一时刻</strong>发生（同时发生）。</li></ul><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E5%B9%B6%E8%A1%8C%E4%B8%8E%E5%B9%B6%E5%8F%91.bmp"></p><p>在操作系统中，安装了多个程序，并发指的是在一段时间内宏观上有多个程序同时运行，这在单 CPU 系统中，每一时刻只能有一道程序执行，即微观上这些程序是分时的交替运行，只不过是给人的感觉是同时运行，那是因为分时交替运行的时间是非常短的。</p><p>而在多个 CPU 系统中，则这些可以并发执行的程序便可以分配到多个处理器上（CPU），实现多任务并行执行，即利用每个处理器来处理一个可以并发执行的程序，这样多个程序便可以同时执行。目前电脑市场上说的多核 CPU，便是多核处理器，核 越多，并行处理的程序越多，能大大的提高电脑运行的效率。</p><blockquote><p>注意：单核处理器的计算机肯定是不能并行的处理多个任务的，只能是多个任务在单个CPU上并发运行。同理,线程也是一样的，从宏观角度上理解线程是并行运行的，但是从微观角度上分析却是串行运行的，即一个线程一个线程的去运行，当系统只有一个CPU时，线程会以某种顺序执行多个线程，我们把这种情况称之为线程调度。</p></blockquote><h2 id="4-2-线程与进程"><a href="#4-2-线程与进程" class="headerlink" title="4.2 线程与进程"></a>4.2 线程与进程</h2><ul><li><p><strong>进程</strong>：是指一个内存中运行的应用程序，每个进程都有一个独立的内存空间，一个应用程序可以同时运行多个进程；进程也是程序的一次执行过程，是系统运行程序的基本单位；系统运行一个程序即是一个进程从创建、运行到消亡的过程。</p></li><li><p><strong>线程</strong>：线程是进程中的一个执行单元，负责当前进程中程序的执行，一个进程中至少有一个线程。一个进程中是可以有多个线程的，这个应用程序也可以称之为多线程程序。 </p><p>简而言之：一个程序运行后至少有一个进程，一个进程中可以包含多个线程 </p></li></ul><p>我们可以再电脑底部任务栏，右键—–&gt;打开任务管理器,可以查看当前任务的进程：</p><p><strong>进程</strong></p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E8%BF%9B%E7%A8%8B%E6%A6%82%E5%BF%B5.png"></p><p><strong>线程</strong></p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E7%BA%BF%E7%A8%8B%E6%A6%82%E5%BF%B5.png"></p><p><strong>线程调度:</strong></p><ul><li><p>分时调度</p><p>所有线程轮流使用 CPU 的使用权，平均分配每个线程占用 CPU 的时间。</p></li><li><p>抢占式调度</p><p>优先让优先级高的线程使用 CPU，如果线程的优先级相同，那么会随机选择一个(线程随机性)，Java使用的为抢占式调度。</p><ul><li>设置线程的优先级</li></ul><p><img src= "/img/loading.gif" data-lazy-src="img/%E8%AE%BE%E7%BD%AE%E7%BA%BF%E7%A8%8B%E4%BC%98%E5%85%88%E7%BA%A7.bmp" alt="设置线程优先级"></p><ul><li> 抢占式调度详解</li></ul><p>  大部分操作系统都支持多进程并发运行，现在的操作系统几乎都支持同时运行多个程序。比如：现在我们上课一边使用编辑器，一边使用录屏软件，同时还开着画图板，dos窗口等软件。此时，这些程序是在同时运行，”感觉这些软件好像在同一时刻运行着“。</p><p>  实际上，CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言，某个时刻，只能执行一个线程，而 CPU的在多个线程间切换速度相对我们的感觉要快，看上去就是在同一时刻运行。<br>  其实，多线程程序并不能提高程序的运行速度，但能够提高程序运行效率，让CPU的使用率更高。</p><p>  <img src= "/img/loading.gif" data-lazy-src="img/%E6%8A%A2%E5%8D%A0%E5%BC%8F%E8%B0%83%E5%BA%A6.bmp" alt="抢占式调度"></p></li></ul><h2 id="4-3-创建线程类"><a href="#4-3-创建线程类" class="headerlink" title="4.3 创建线程类"></a>4.3 创建线程类</h2><p>Java使用<code>java.lang.Thread</code>类代表<strong>线程</strong>，所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务，实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。Java中通过继承Thread类来<strong>创建</strong>并<strong>启动多线程</strong>的步骤如下：</p><ol><li>定义Thread类的子类，并重写该类的run()方法，该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。</li><li>创建Thread子类的实例，即创建了线程对象</li><li>调用线程对象的start()方法来启动该线程</li></ol><p>代码如下：</p><p>测试类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//创建自定义线程对象</span></span><br><span class="line">        MyThread mt = <span class="keyword">new</span> MyThread(<span class="string">&quot;新的线程！&quot;</span>);</span><br><span class="line">        <span class="comment">//开启新线程</span></span><br><span class="line">        mt.start();</span><br><span class="line">        <span class="comment">//在主方法中执行for循环</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;main线程！&quot;</span>+i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>自定义线程类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line">    <span class="comment">//定义指定线程名称的构造方法</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MyThread</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//调用父类的String参数的构造方法，指定线程的名称</span></span><br><span class="line">        <span class="keyword">super</span>(name);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 重写run方法，完成该线程执行的逻辑</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">            System.out.println(getName()+<span class="string">&quot;：正在执行！&quot;</span>+i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>tomcat的配置以及使用</title>
      <link href="java/javaold/tomcat/"/>
      <url>java/javaold/tomcat/</url>
      
        <content type="html"><![CDATA[<h3 id="tomcat-概述"><a href="#tomcat-概述" class="headerlink" title="tomcat 概述"></a>tomcat 概述</h3><p>Tomcat 服务器是一个免费的开放源代码的Web 应用服务器</p><h3 id="1-下载"><a href="#1-下载" class="headerlink" title="1.下载"></a>1.下载</h3><p>tomcat的官方网站:<a href="https://tomcat.apache.org/">https://tomcat.apache.org/</a></p><h3 id="2-安装"><a href="#2-安装" class="headerlink" title="2.安装"></a>2.安装</h3><p>解压缩到哪就行了,不用安装的</p><h3 id="3-卸载"><a href="#3-卸载" class="headerlink" title="3.卸载"></a>3.卸载</h3><p>删除目录即可</p><h3 id="4-启动"><a href="#4-启动" class="headerlink" title="4.启动"></a>4.启动</h3><ul><li>bin/startup.bat ,双击运行该文件即可</li><li>访问:在浏览器输入<a href="http://localhost:8080/">http://localhost:8080</a> 回车访问<pre><code>  http://othersid:8080 访问别人</code></pre></li><li>可能遇到的问题:<ol><li>黑窗口一闪而过:<ul><li>原因: 没有正确配置JAVA_HOME环境变量</li><li>解决方案: 正确配置一下环境变量,并将jdk中的bin文件夹的那个就是path中的变量用%JAVA_HOME%来哦替换即可</li></ul></li><li>启动报错:<ol><li>暴力:找到占用的端口号,并且找到对应的进程,杀死该进程<ul><li>netstat -ano</li></ul></li><li>温柔:修改自身的端口号<ul><li>conf/server.xml</li><li><Connector port="8888" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8445"/></li><li>一般会将tomcat默认端口号修改为80.80端口号是<code>http</code>协议默认的端口号<ul><li>好处:在访问的时候,就不用输入端口号了</li></ul></li></ul></li></ol></li></ol></li></ul><h3 id="5-关闭"><a href="#5-关闭" class="headerlink" title="5. 关闭"></a>5. 关闭</h3><ol><li>正常关闭:<ul><li>bin/shutdown.bat</li><li>ctrl+c</li></ul></li><li>强制关闭:<ul><li>点击启动窗口的X</li></ul></li></ol><h3 id="6-配置"><a href="#6-配置" class="headerlink" title="6.配置"></a>6.配置</h3><h4 id="部署项目的方式"><a href="#部署项目的方式" class="headerlink" title="部署项目的方式:"></a>部署项目的方式:</h4><ol><li>直接将项目放到webapps目录下面即可.<ul><li>/hello: 项目的访问路径–&gt;虚拟路径</li><li>简化部署:将项目打成一个war包,再将war包放置到webapps目录下面.<ul><li>war包会自动解压缩</li></ul></li></ul></li><li>配置conf/server.xml文件<br> 在<Host>标签体中配置 <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Context</span> <span class="attr">docBase</span>=<span class="string">&quot;D:\hello&quot;</span> <span class="attr">path</span>=<span class="string">&quot;/hehe&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure><ul><li>docBase:项目存放的路径</li><li>path:虚拟目录</li></ul></li><li>在conf\Catalina\localhost创建任意名称的xml文件.在文件中编写<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Context</span> <span class="attr">docBase</span>=<span class="string">&quot;E:\hello&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure></li></ol><ul><li>虚拟目录:xml文件的名称    </li></ul><h4 id="静态项目和动态项目"><a href="#静态项目和动态项目" class="headerlink" title="静态项目和动态项目"></a>静态项目和动态项目</h4><ul><li>目录结构<ul><li>java 动态项目的目录结构:<br>  – 项目的根目录<pre><code>  -- web-INF目录:      -- web.xml:web项目的核心配置文件(下面那俩可以没有,这个得有)      -- classes目录:放置字节码我呢间的目录      -- libmul:放置依赖的jar包</code></pre></li></ul></li></ul><h4 id="将tomcat集成到IDEA中-并且创建JavaEE的项目-部署项目"><a href="#将tomcat集成到IDEA中-并且创建JavaEE的项目-部署项目" class="headerlink" title="将tomcat集成到IDEA中, 并且创建JavaEE的项目,部署项目."></a>将tomcat集成到IDEA中, 并且创建JavaEE的项目,部署项目.</h4><p>更新</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>在IDEA中调试代码</title>
      <link href="ide/jetbrains/idea/jetbrains-idea-debug/"/>
      <url>ide/jetbrains/idea/jetbrains-idea-debug/</url>
      
        <content type="html"><![CDATA[<h3 id="Debug调试程序："><a href="#Debug调试程序：" class="headerlink" title="Debug调试程序："></a>Debug调试程序：</h3><p>可以让代码逐步执行，查看代码执行的过程,调试程序中出现的bug</p><h3 id="使用方式"><a href="#使用方式" class="headerlink" title="使用方式:"></a>使用方式:</h3><p>在行号的右边,鼠标左键单击,添加断点(每个方法的第一行,哪里有bug添加到哪里)</p><p>右键,选择debug执行程序</p><p>程序就会停留在添加的第一个断点处</p><h3 id="执行程序"><a href="#执行程序" class="headerlink" title="执行程序:"></a>执行程序:</h3><ul><li>f8:逐行执行程序</li><li>f7:进入到方法中</li><li>shift+f8:跳出方法</li><li>f9:跳到下一个断点</li><li>ctrl+f2:退出debug模式,停止程序</li><li>console控制台</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> idea </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记07-List、Set、数据结构、Collections</title>
      <link href="java/javase/note/note07/"/>
      <url>java/javase/note/note07/</url>
      
        <content type="html"><![CDATA[<h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li>数据结构</li><li>List集合</li><li>Set集合</li><li>Collections</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><ul><li><input disabled="" type="checkbox"> 能够说出List集合特点</li><li><input disabled="" type="checkbox"> 能够说出常见的数据结构</li><li><input disabled="" type="checkbox"> 能够说出数组结构特点</li><li><input disabled="" type="checkbox"> 能够说出栈结构特点</li><li><input disabled="" type="checkbox"> 能够说出队列结构特点</li><li><input disabled="" type="checkbox"> 能够说出单向链表结构特点</li><li><input disabled="" type="checkbox"> 能够说出Set集合的特点</li><li><input disabled="" type="checkbox"> 能够说出哈希表的特点</li><li><input disabled="" type="checkbox"> 使用HashSet集合存储自定义元素</li><li><input disabled="" type="checkbox"> 能够说出可变参数的格式</li><li><input disabled="" type="checkbox"> 能够使用集合工具类</li><li><input disabled="" type="checkbox"> 能够使用Comparator比较器进行排序</li></ul><h1 id="第一章-数据结构"><a href="#第一章-数据结构" class="headerlink" title="第一章 数据结构"></a>第一章 数据结构</h1><h2 id="2-1-数据结构有什么用？"><a href="#2-1-数据结构有什么用？" class="headerlink" title="2.1 数据结构有什么用？"></a>2.1 数据结构有什么用？</h2><p>当你用着java里面的容器类很爽的时候，你有没有想过，怎么ArrayList就像一个无限扩充的数组，也好像链表之类的。好用吗？好用，这就是数据结构的用处，只不过你在不知不觉中使用了。</p><p>现实世界的存储，我们使用的工具和建模。每种数据结构有自己的优点和缺点，想想如果Google的数据用的是数组的存储，我们还能方便地查询到所需要的数据吗？而算法，在这么多的数据中如何做到最快的插入，查找，删除，也是在追求更快。</p><p>我们java是面向对象的语言，就好似自动档轿车，C语言好似手动档吉普。数据结构呢？是变速箱的工作原理。你完全可以不知道变速箱怎样工作，就把自动档的车子从 A点 开到 B点，而且未必就比懂得的人慢。写程序这件事，和开车一样，经验可以起到很大作用，但如果你不知道底层是怎么工作的，就永远只能开车，既不会修车，也不能造车。当然了，数据结构内容比较多，细细的学起来也是相对费功夫的，不可能达到一蹴而就。我们将常见的数据结构：堆栈、队列、数组、链表和红黑树 这几种给大家介绍一下，作为数据结构的入门，了解一下它们的特点即可。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E6%AF%94%E5%96%BB.png"></p><h2 id="2-2-常见的数据结构"><a href="#2-2-常见的数据结构" class="headerlink" title="2.2 常见的数据结构"></a>2.2 常见的数据结构</h2><p>数据存储的常用结构有：栈、队列、数组、链表和红黑树。我们分别来了解一下：</p><h4 id="栈"><a href="#栈" class="headerlink" title="栈"></a>栈</h4><ul><li><strong>栈</strong>：<strong>stack</strong>,又称堆栈，它是运算受限的线性表，其限制是仅允许在标的一端进行插入和删除操作，不允许在其他任何位置进行添加、查找、删除等操作。</li></ul><p>简单的说：采用该结构的集合，对元素的存取有如下的特点</p><ul><li><p>先进后出（即，存进去的元素，要在后它后面的元素依次取出后，才能取出该元素）。例如，子弹压进弹夹，先压进去的子弹在下面，后压进去的子弹在上面，当开枪时，先弹出上面的子弹，然后才能弹出下面的子弹。</p></li><li><p>栈的入口、出口的都是栈的顶端位置。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E5%A0%86%E6%A0%88.png"></p></li></ul><p>这里两个名词需要注意：</p><ul><li><strong>压栈</strong>：就是存元素。即，把元素存储到栈的顶端位置，栈中已有元素依次向栈底方向移动一个位置。</li><li><strong>弹栈</strong>：就是取元素。即，把栈的顶端位置元素取出，栈中已有元素依次向栈顶方向移动一个位置。</li></ul><h4 id="队列"><a href="#队列" class="headerlink" title="队列"></a>队列</h4><ul><li><strong>队列</strong>：<strong>queue</strong>,简称队，它同堆栈一样，也是一种运算受限的线性表，其限制是仅允许在表的一端进行插入，而在表的另一端进行删除。</li></ul><p>简单的说，采用该结构的集合，对元素的存取有如下的特点：</p><ul><li>先进先出（即，存进去的元素，要在后它前面的元素依次取出后，才能取出该元素）。例如，小火车过山洞，车头先进去，车尾后进去；车头先出来，车尾后出来。</li><li>队列的入口、出口各占一侧。例如，下图中的左侧为入口，右侧为出口。</li></ul><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E9%98%9F%E5%88%97%E5%9B%BE.bmp"></p><h4 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h4><ul><li><strong>数组</strong>:<strong>Array</strong>,是有序的元素序列，数组是在内存中开辟一段连续的空间，并在此空间存放元素。就像是一排出租屋，有100个房间，从001到100每个房间都有固定编号，通过编号就可以快速找到租房子的人。</li></ul><p>简单的说,采用该结构的集合，对元素的存取有如下的特点：</p><ul><li><p>查找元素快：通过索引，可以快速访问指定位置的元素</p><p> <img src= "/img/loading.gif" data-lazy-src="img/%E6%95%B0%E7%BB%84%E6%9F%A5%E8%AF%A2%E5%BF%AB.png"></p></li><li><p> 增删元素慢</p></li><li><p><strong>指定索引位置增加元素</strong>：需要创建一个新数组，将指定新元素存储在指定索引位置，再把原数组元素根据索引，复制到新数组对应索引的位置。如下图<img src= "/img/loading.gif" data-lazy-src="img/%E6%95%B0%E7%BB%84%E6%B7%BB%E5%8A%A0.png"></p></li><li><p><strong>指定索引位置删除元素：</strong>需要创建一个新数组，把原数组元素根据索引，复制到新数组对应索引的位置，原数组中指定索引位置元素不复制到新数组中。如下图<img src= "/img/loading.gif" data-lazy-src="img/%E6%95%B0%E7%BB%84%E5%88%A0%E9%99%A4.png"></p></li></ul><h4 id="链表"><a href="#链表" class="headerlink" title="链表"></a>链表</h4><ul><li><p><strong>链表</strong>:<strong>linked list</strong>,由一系列结点node（链表中每一个元素称为结点）组成，结点可以在运行时i动态生成。每个结点包括两个部分：一个是存储数据元素的数据域，另一个是存储下一个结点地址的指针域。我们常说的链表结构有单向链表与双向链表，那么这里给大家介绍的是<strong>单向链表</strong>。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E5%8D%95%E9%93%BE%E8%A1%A8%E7%BB%93%E6%9E%84%E7%89%B9%E7%82%B9.png"></p></li></ul><p>简单的说，采用该结构的集合，对元素的存取有如下的特点：</p><ul><li><p>多个结点之间，通过地址进行连接。例如，多个人手拉手，每个人使用自己的右手拉住下个人的左手，依次类推，这样多个人就连在一起了。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E5%8D%95%E9%93%BE%E8%A1%A8%E7%BB%93%E6%9E%84.png"></p></li><li><p>查找元素慢：想查找某个元素，需要通过连接的节点，依次向后查找指定元素</p></li><li><p>增删元素快：</p><ul><li> 增加元素：只需要修改连接下个元素的地址即可。</li></ul><p>  <img src= "/img/loading.gif" data-lazy-src="img%5C%E5%A2%9E%E5%8A%A0%E7%BB%93%E7%82%B9.png"></p><ul><li> 删除元素：只需要修改连接下个元素的地址即可。</li></ul><p>  <img src= "/img/loading.gif" data-lazy-src="img%5C%E5%88%A0%E9%99%A4%E7%BB%93%E7%82%B9.bmp"></p></li></ul><h4 id="红黑树"><a href="#红黑树" class="headerlink" title="红黑树"></a>红黑树</h4><ul><li><strong>二叉树</strong>：<strong>binary tree</strong> ,是每个结点不超过2的有序<strong>树（tree）</strong> 。</li></ul><p>简单的理解，就是一种类似于我们生活中树的结构，只不过每个结点上都最多只能有两个子结点。</p><p>二叉树是每个节点最多有两个子树的树结构。顶上的叫根结点，两边被称作“左子树”和“右子树”。</p><p>如图：</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E4%BA%8C%E5%8F%89%E6%A0%91.bmp"></p><p>我们要说的是二叉树的一种比较有意思的叫做<strong>红黑树</strong>，红黑树本身就是一颗二叉查找树，将节点插入后，该树仍然是一颗二叉查找树。也就意味着，树的键值仍然是有序的。</p><p>红黑树的约束:</p><ol><li>节点可以是红色的或者黑色的</li></ol><ol start="2"><li>根节点是黑色的</li></ol><ol start="3"><li>叶子节点(特指空节点)是黑色的</li><li>每个红色节点的子节点都是黑色的</li><li>任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同</li></ol><p>红黑树的特点:</p><p>​    速度特别快,趋近平衡树,查找叶子元素最少和最多次数不多于二倍</p><h1 id="第二章-List集合"><a href="#第二章-List集合" class="headerlink" title="第二章 List集合"></a>第二章 List集合</h1><p>我们掌握了Collection接口的使用后，再来看看Collection接口中的子类，他们都具备那些特性呢？</p><p>接下来，我们一起学习Collection中的常用几个子类（<code>java.util.List</code>集合、<code>java.util.Set</code>集合）。</p><h2 id="1-1-List接口介绍"><a href="#1-1-List接口介绍" class="headerlink" title="1.1 List接口介绍"></a>1.1 List接口介绍</h2><p><code>java.util.List</code>接口继承自<code>Collection</code>接口，是单列集合的一个重要分支，习惯性地会将实现了<code>List</code>接口的对象称为List集合。在List集合中允许出现重复的元素，所有的元素是以一种线性方式进行存储的，在程序中可以通过索引来访问集合中的指定元素。另外，List集合还有一个特点就是元素有序，即元素的存入顺序和取出顺序一致。</p><p>看完API，我们总结一下：</p><p>List接口特点：</p><ol><li>它是一个元素存取有序的集合。例如，存元素的顺序是11、22、33。那么集合中，元素的存储就是按照11、22、33的顺序完成的）。</li><li>它是一个带有索引的集合，通过索引就可以精确的操作集合中的元素（与数组的索引是一个道理）。</li><li>集合中可以有重复的元素，通过元素的equals方法，来比较是否为重复的元素。</li></ol><blockquote><p>tips:我们在基础班的时候已经学习过List接口的子类java.util.ArrayList类，该类中的方法都是来自List中定义。</p></blockquote><h2 id="1-2-List接口中常用方法"><a href="#1-2-List接口中常用方法" class="headerlink" title="1.2 List接口中常用方法"></a>1.2 List接口中常用方法</h2><p>List作为Collection集合的子接口，不但继承了Collection接口中的全部方法，而且还增加了一些根据元素索引来操作集合的特有方法，如下：</p><ul><li><code>public void add(int index, E element)</code>: 将指定的元素，添加到该集合中的指定位置上。</li><li><code>public E get(int index)</code>:返回集合中指定位置的元素。</li><li><code>public E remove(int index)</code>: 移除列表中指定位置的元素, 返回的是被移除的元素。</li><li><code>public E set(int index, E element)</code>:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。</li></ul><p>List集合特有的方法都是跟索引相关，我们在基础班都学习过，那么我们再来复习一遍吧：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ListDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="comment">// 创建List集合对象</span></span><br><span class="line">    List&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 往 尾部添加 指定元素</span></span><br><span class="line">    list.add(<span class="string">&quot;图图&quot;</span>);</span><br><span class="line">    list.add(<span class="string">&quot;小美&quot;</span>);</span><br><span class="line">    list.add(<span class="string">&quot;不高兴&quot;</span>);</span><br><span class="line">    </span><br><span class="line">    System.out.println(list);</span><br><span class="line">    <span class="comment">// add(int index,String s) 往指定位置添加</span></span><br><span class="line">    list.add(<span class="number">1</span>,<span class="string">&quot;没头脑&quot;</span>);</span><br><span class="line">    </span><br><span class="line">    System.out.println(list);</span><br><span class="line">    <span class="comment">// String remove(int index) 删除指定位置元素  返回被删除元素</span></span><br><span class="line">    <span class="comment">// 删除索引位置为2的元素 </span></span><br><span class="line">    System.out.println(<span class="string">&quot;删除索引位置为2的元素&quot;</span>);</span><br><span class="line">    System.out.println(list.remove(<span class="number">2</span>));</span><br><span class="line">    </span><br><span class="line">    System.out.println(list);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// String set(int index,String s)</span></span><br><span class="line">    <span class="comment">// 在指定位置 进行 元素替代（改） </span></span><br><span class="line">    <span class="comment">// 修改指定位置元素</span></span><br><span class="line">    list.set(<span class="number">0</span>, <span class="string">&quot;三毛&quot;</span>);</span><br><span class="line">    System.out.println(list);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// String get(int index)  获取指定位置元素</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 跟size() 方法一起用  来 遍历的 </span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>;i&lt;list.size();i++)&#123;</span><br><span class="line">    System.out.println(list.get(i));</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//还可以使用增强for</span></span><br><span class="line">    <span class="keyword">for</span> (String string : list) &#123;</span><br><span class="line">System.out.println(string);</span><br><span class="line">&#125;  </span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第三章-List的子类"><a href="#第三章-List的子类" class="headerlink" title="第三章 List的子类"></a>第三章 List的子类</h1><h2 id="3-1-ArrayList集合"><a href="#3-1-ArrayList集合" class="headerlink" title="3.1 ArrayList集合"></a>3.1 ArrayList集合</h2><p><code>java.util.ArrayList</code>集合数据存储的结构是数组结构。元素增删慢，查找快，由于日常开发中使用最多的功能为查询数据、遍历数据，所以<code>ArrayList</code>是最常用的集合。</p><p>许多程序员开发时非常随意地使用ArrayList完成任何需求，并不严谨，这种用法是不提倡的。</p><h2 id="3-2-LinkedList集合"><a href="#3-2-LinkedList集合" class="headerlink" title="3.2 LinkedList集合"></a>3.2 LinkedList集合</h2><p><code>java.util.LinkedList</code>集合数据存储的结构是链表结构。方便元素添加、删除的集合。</p><blockquote><p>LinkedList是一个双向链表，那么双向链表是什么样子的呢，我们用个图了解下</p></blockquote><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8.png"></p><p>实际开发中对一个集合元素的添加与删除经常涉及到首尾操作，而LinkedList提供了大量首尾操作的方法。这些方法我们作为了解即可：</p><ul><li><code>public void addFirst(E e)</code>:将指定元素插入此列表的开头。</li><li><code>public void addLast(E e)</code>:将指定元素添加到此列表的结尾。</li><li><code>public E getFirst()</code>:返回此列表的第一个元素。</li><li><code>public E getLast()</code>:返回此列表的最后一个元素。</li><li><code>public E removeFirst()</code>:移除并返回此列表的第一个元素。</li><li><code>public E removeLast()</code>:移除并返回此列表的最后一个元素。</li><li><code>public E pop()</code>:从此列表所表示的堆栈处弹出一个元素。</li><li><code>public void push(E e)</code>:将元素推入此列表所表示的堆栈。</li><li><code>public boolean isEmpty()</code>：如果列表不包含元素，则返回true。</li></ul><p>LinkedList是List的子类，List中的方法LinkedList都是可以使用，这里就不做详细介绍，我们只需要了解LinkedList的特有方法即可。在开发时，LinkedList集合也可以作为堆栈，队列的结构使用。（了解即可）</p><p>方法演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LinkedListDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        LinkedList&lt;String&gt; link = <span class="keyword">new</span> LinkedList&lt;String&gt;();</span><br><span class="line">        <span class="comment">//添加元素</span></span><br><span class="line">        link.addFirst(<span class="string">&quot;abc1&quot;</span>);</span><br><span class="line">        link.addFirst(<span class="string">&quot;abc2&quot;</span>);</span><br><span class="line">        link.addFirst(<span class="string">&quot;abc3&quot;</span>);</span><br><span class="line">        System.out.println(link);</span><br><span class="line">        <span class="comment">// 获取元素</span></span><br><span class="line">        System.out.println(link.getFirst());</span><br><span class="line">        System.out.println(link.getLast());</span><br><span class="line">        <span class="comment">// 删除元素</span></span><br><span class="line">        System.out.println(link.removeFirst());</span><br><span class="line">        System.out.println(link.removeLast());</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (!link.isEmpty()) &#123; <span class="comment">//判断集合是否为空</span></span><br><span class="line">            System.out.println(link.pop()); <span class="comment">//弹出集合中的栈顶元素</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        System.out.println(link);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第四章-Set接口"><a href="#第四章-Set接口" class="headerlink" title="第四章 Set接口"></a>第四章 Set接口</h1><p><code>java.util.Set</code>接口和<code>java.util.List</code>接口一样，同样继承自<code>Collection</code>接口，它与<code>Collection</code>接口中的方法基本一致，并没有对<code>Collection</code>接口进行功能上的扩充，只是比<code>Collection</code>接口更加严格了。与<code>List</code>接口不同的是，<code>Set</code>接口中元素无序，并且都会以某种规则保证存入的元素不出现重复。</p><p><code>Set</code>集合有多个子类，这里我们介绍其中的<code>java.util.HashSet</code>、<code>java.util.LinkedHashSet</code>这两个集合。</p><blockquote><p>tips:Set集合取出元素的方式可以采用：迭代器、增强for。</p></blockquote><h2 id="3-1-HashSet集合介绍"><a href="#3-1-HashSet集合介绍" class="headerlink" title="3.1 HashSet集合介绍"></a>3.1 HashSet集合介绍</h2><p><code>java.util.HashSet</code>是<code>Set</code>接口的一个实现类，它所存储的元素是不可重复的，并且元素都是无序的(即存取顺序不一致)。<code>java.util.HashSet</code>底层的实现其实是一个<code>java.util.HashMap</code>支持，由于我们暂时还未学习，先做了解。</p><p><code>HashSet</code>是根据对象的哈希值来确定元素在集合中的存储位置，因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于：<code>hashCode</code>与<code>equals</code>方法。</p><p>我们先来使用一下Set集合存储，看下现象，再进行原理的讲解:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HashSetDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//创建 Set集合</span></span><br><span class="line">        HashSet&lt;String&gt;  set = <span class="keyword">new</span> HashSet&lt;String&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//添加元素</span></span><br><span class="line">        set.add(<span class="keyword">new</span> String(<span class="string">&quot;cba&quot;</span>));</span><br><span class="line">        set.add(<span class="string">&quot;abc&quot;</span>);</span><br><span class="line">        set.add(<span class="string">&quot;bac&quot;</span>); </span><br><span class="line">        set.add(<span class="string">&quot;cba&quot;</span>);  </span><br><span class="line">        <span class="comment">//遍历</span></span><br><span class="line">        <span class="keyword">for</span> (String name : set) &#123;</span><br><span class="line">            System.out.println(name);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>输出结果如下，说明集合中不能存储重复元素：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cba</span><br><span class="line">abc</span><br><span class="line">bac</span><br></pre></td></tr></table></figure><blockquote><p>tips:根据结果我们发现字符串”cba”只存储了一个，也就是说重复的元素set集合不存储。</p></blockquote><h2 id="2-2-HashSet集合存储数据的结构（哈希表）"><a href="#2-2-HashSet集合存储数据的结构（哈希表）" class="headerlink" title="2.2  HashSet集合存储数据的结构（哈希表）"></a>2.2  HashSet集合存储数据的结构（哈希表）</h2><p>什么是哈希表呢？</p><p>在<strong>JDK1.8</strong>之前，哈希表底层采用数组+链表实现，即使用链表处理冲突，同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多，即hash值相等的元素较多时，通过key值依次查找的效率较低。而JDK1.8中，哈希表存储采用数组+链表+红黑树实现，当链表长度超过阈值（8）时，将链表转换为红黑树，这样大大减少了查找时间。</p><p>简单的来说，哈希表是由数组+链表+红黑树（JDK1.8增加了红黑树部分）实现的，如下图所示。<img src= "/img/loading.gif" data-lazy-src="img%5C%E5%93%88%E5%B8%8C%E8%A1%A8.png"></p><p>看到这张图就有人要问了，这个是怎么存储的呢？</p><p>为了方便大家的理解我们结合一个存储流程图来说明一下：</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E5%93%88%E5%B8%8C%E6%B5%81%E7%A8%8B%E5%9B%BE.png"></p><p>总而言之，<strong>JDK1.8</strong>引入红黑树大程度优化了HashMap的性能，那么对于我们来讲保证HashSet集合元素的唯一，其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象，那么保证其唯一，就必须复写hashCode和equals方法建立属于当前对象的比较方式。</p><h2 id="2-3-HashSet存储自定义类型元素"><a href="#2-3-HashSet存储自定义类型元素" class="headerlink" title="2.3  HashSet存储自定义类型元素"></a>2.3  HashSet存储自定义类型元素</h2><p>给HashSet中存放自定义类型元素时，需要重写对象中的hashCode和equals方法，建立自己的比较方式，才能保证HashSet集合中的对象唯一</p><p>创建自定义Student类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Student</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">(String name, <span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">        <span class="keyword">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAge</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAge</span><span class="params">(<span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object o)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span> == o)</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        <span class="keyword">if</span> (o == <span class="keyword">null</span> || getClass() != o.getClass())</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        Student student = (Student) o;</span><br><span class="line">        <span class="keyword">return</span> age == student.age &amp;&amp;</span><br><span class="line">               Objects.equals(name, student.name);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hashCode</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> Objects.hash(name, age);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HashSetDemo2</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//创建集合对象   该集合中存储 Student类型对象</span></span><br><span class="line">        HashSet&lt;Student&gt; stuSet = <span class="keyword">new</span> HashSet&lt;Student&gt;();</span><br><span class="line">        <span class="comment">//存储 </span></span><br><span class="line">        Student stu = <span class="keyword">new</span> Student(<span class="string">&quot;于谦&quot;</span>, <span class="number">43</span>);</span><br><span class="line">        stuSet.add(stu);</span><br><span class="line">        stuSet.add(<span class="keyword">new</span> Student(<span class="string">&quot;郭德纲&quot;</span>, <span class="number">44</span>));</span><br><span class="line">        stuSet.add(<span class="keyword">new</span> Student(<span class="string">&quot;于谦&quot;</span>, <span class="number">43</span>));</span><br><span class="line">        stuSet.add(<span class="keyword">new</span> Student(<span class="string">&quot;郭麒麟&quot;</span>, <span class="number">23</span>));</span><br><span class="line">        stuSet.add(stu);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (Student stu2 : stuSet) &#123;</span><br><span class="line">            System.out.println(stu2);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">执行结果：</span><br><span class="line">Student [name=郭德纲, age=<span class="number">44</span>]</span><br><span class="line">Student [name=于谦, age=<span class="number">43</span>]</span><br><span class="line">Student [name=郭麒麟, age=<span class="number">23</span>]</span><br></pre></td></tr></table></figure><h2 id="2-3-LinkedHashSet"><a href="#2-3-LinkedHashSet" class="headerlink" title="2.3 LinkedHashSet"></a>2.3 LinkedHashSet</h2><p>我们知道HashSet保证元素唯一，可是元素存放进去是没有顺序的，那么我们要保证有序，怎么办呢？</p><p>在HashSet下面有一个子类<code>java.util.LinkedHashSet</code>，它是链表和哈希表组合的一个数据存储结构。</p><p>演示代码如下:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LinkedHashSetDemo</span> </span>&#123;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">Set&lt;String&gt; set = <span class="keyword">new</span> LinkedHashSet&lt;String&gt;();</span><br><span class="line">set.add(<span class="string">&quot;bbb&quot;</span>);</span><br><span class="line">set.add(<span class="string">&quot;aaa&quot;</span>);</span><br><span class="line">set.add(<span class="string">&quot;abc&quot;</span>);</span><br><span class="line">set.add(<span class="string">&quot;bbc&quot;</span>);</span><br><span class="line">        Iterator&lt;String&gt; it = set.iterator();</span><br><span class="line"><span class="keyword">while</span> (it.hasNext()) &#123;</span><br><span class="line">System.out.println(it.next());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">结果：</span><br><span class="line">  bbb</span><br><span class="line">  aaa</span><br><span class="line">  abc</span><br><span class="line">  bbc</span><br></pre></td></tr></table></figure><h2 id="1-9-可变参数"><a href="#1-9-可变参数" class="headerlink" title="1.9  可变参数"></a>1.9  可变参数</h2><p>在<strong>JDK1.5</strong>之后，如果我们定义一个方法需要接受多个参数，并且多个参数类型一致，我们可以对其简化成如下格式：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">修饰符 返回值类型 方法名(参数类型... 形参名)&#123;  &#125;</span><br></pre></td></tr></table></figure><p>其实这个书写完全等价与</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">修饰符 返回值类型 方法名(参数类型[] 形参名)&#123;  &#125;</span><br></pre></td></tr></table></figure><p>只是后面这种定义，在调用时必须传递数组，而前者可以直接传递数据即可。</p><p><strong>JDK1.5</strong>以后。出现了简化操作。**…** 用在参数上，称之为可变参数。</p><p>同样是代表数组，但是在调用这个带有可变参数的方法时，不用创建数组(这就是简单之处)，直接将数组中的元素作为实际参数进行传递，其实编译成的class文件，将这些元素先封装到一个数组中，在进行传递。这些动作都在编译.class文件时，自动完成了。</p><p>代码演示：    </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ChangeArgs</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] arr = &#123; <span class="number">1</span>, <span class="number">4</span>, <span class="number">62</span>, <span class="number">431</span>, <span class="number">2</span> &#125;;</span><br><span class="line">        <span class="keyword">int</span> sum = getSum(arr);</span><br><span class="line">        System.out.println(sum);</span><br><span class="line">        <span class="comment">//  6  7  2 12 2121</span></span><br><span class="line">        <span class="comment">// 求 这几个元素和 6  7  2 12 2121</span></span><br><span class="line">        <span class="keyword">int</span> sum2 = getSum(<span class="number">6</span>, <span class="number">7</span>, <span class="number">2</span>, <span class="number">12</span>, <span class="number">2121</span>);</span><br><span class="line">        System.out.println(sum2);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 完成数组  所有元素的求和 原始写法</span></span><br><span class="line"><span class="comment">     </span></span><br><span class="line"><span class="comment">      public static int getSum(int[] arr)&#123;</span></span><br><span class="line"><span class="comment">        int sum = 0;</span></span><br><span class="line"><span class="comment">        for(int a : arr)&#123;</span></span><br><span class="line"><span class="comment">            sum += a;</span></span><br><span class="line"><span class="comment">        &#125;</span></span><br><span class="line"><span class="comment">        </span></span><br><span class="line"><span class="comment">        return sum;</span></span><br><span class="line"><span class="comment">      &#125;</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">    <span class="comment">//可变参数写法</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getSum</span><span class="params">(<span class="keyword">int</span>... arr)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> a : arr) &#123;</span><br><span class="line">            sum += a;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> sum;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>tips: 上述add方法在同一个类中，只能存在一个。因为会发生调用的不确定性</p><p>注意：如果在方法书写时，这个方法拥有多参数，参数中包含可变参数，可变参数一定要写在参数列表的末尾位置。</p></blockquote><h1 id="第五章-Collections"><a href="#第五章-Collections" class="headerlink" title="第五章  Collections"></a>第五章  Collections</h1><h2 id="2-1-常用功能"><a href="#2-1-常用功能" class="headerlink" title="2.1 常用功能"></a>2.1 常用功能</h2><ul><li><code>java.utils.Collections</code>是集合工具类，用来对集合进行操作。部分方法如下：</li></ul><ul><li><code>public static &lt;T&gt; boolean addAll(Collection&lt;T&gt; c, T... elements)  </code>:往集合中添加一些元素。</li><li><code>public static void shuffle(List&lt;?&gt; list) 打乱顺序</code>:打乱集合顺序。</li><li><code>public static &lt;T&gt; void sort(List&lt;T&gt; list)</code>:将集合中元素按照默认规则排序。</li><li><code>public static &lt;T&gt; void sort(List&lt;T&gt; list，Comparator&lt;? super T&gt; )</code>:将集合中元素按照指定规则排序。</li></ul><p>代码演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CollectionsDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        ArrayList&lt;Integer&gt; list = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">        <span class="comment">//原来写法</span></span><br><span class="line">        <span class="comment">//list.add(12);</span></span><br><span class="line">        <span class="comment">//list.add(14);</span></span><br><span class="line">        <span class="comment">//list.add(15);</span></span><br><span class="line">        <span class="comment">//list.add(1000);</span></span><br><span class="line">        <span class="comment">//采用工具类 完成 往集合中添加元素  </span></span><br><span class="line">        Collections.addAll(list, <span class="number">5</span>, <span class="number">222</span>, <span class="number">1</span>，<span class="number">2</span>);</span><br><span class="line">        System.out.println(list);</span><br><span class="line">        <span class="comment">//排序方法 </span></span><br><span class="line">        Collections.sort(list);</span><br><span class="line">        System.out.println(list);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">结果：</span><br><span class="line">[<span class="number">5</span>, <span class="number">222</span>, <span class="number">1</span>, <span class="number">2</span>]</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">5</span>, <span class="number">222</span>]</span><br></pre></td></tr></table></figure><p>代码演示之后 ，发现我们的集合按照顺序进行了排列，可是这样的顺序是采用默认的顺序，如果想要指定顺序那该怎么办呢？</p><p>我们发现还有个方法没有讲，<code>public static &lt;T&gt; void sort(List&lt;T&gt; list，Comparator&lt;? super T&gt; )</code>:将集合中元素按照指定规则排序。接下来讲解一下指定规则的排列。</p><h2 id="2-2-Comparator比较器"><a href="#2-2-Comparator比较器" class="headerlink" title="2.2 Comparator比较器"></a>2.2 Comparator比较器</h2><p>我们还是先研究这个方法</p><p><code>public static &lt;T&gt; void sort(List&lt;T&gt; list)</code>:将集合中元素按照默认规则排序。</p><p>不过这次存储的是字符串类型。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CollectionsDemo2</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        ArrayList&lt;String&gt;  list = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">        list.add(<span class="string">&quot;cba&quot;</span>);</span><br><span class="line">        list.add(<span class="string">&quot;aba&quot;</span>);</span><br><span class="line">        list.add(<span class="string">&quot;sba&quot;</span>);</span><br><span class="line">        list.add(<span class="string">&quot;nba&quot;</span>);</span><br><span class="line">        <span class="comment">//排序方法</span></span><br><span class="line">        Collections.sort(list);</span><br><span class="line">        System.out.println(list);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[aba, cba, nba, sba]</span><br></pre></td></tr></table></figure><p>我们使用的是默认的规则完成字符串的排序，那么默认规则是怎么定义出来的呢？</p><p>说到排序了，简单的说就是两个对象之间比较大小，那么在JAVA中提供了两种比较实现的方式，一种是比较死板的采用<code>java.lang.Comparable</code>接口去实现，一种是灵活的当我需要做排序的时候在去选择的<code>java.util.Comparator</code>接口完成。</p><p>那么我们采用的<code>public static &lt;T&gt; void sort(List&lt;T&gt; list)</code>这个方法完成的排序，实际上要求了被排序的类型需要实现Comparable接口完成比较的功能，在String类型上如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">String</span> <span class="keyword">implements</span> <span class="title">java</span>.<span class="title">io</span>.<span class="title">Serializable</span>, <span class="title">Comparable</span>&lt;<span class="title">String</span>&gt;, <span class="title">CharSequence</span> </span>&#123;</span><br></pre></td></tr></table></figure><p>String类实现了这个接口，并完成了比较规则的定义，但是这样就把这种规则写死了，那比如我想要字符串按照第一个字符降序排列，那么这样就要修改String的源代码，这是不可能的了，那么这个时候我们可以使用</p><p><code>public static &lt;T&gt; void sort(List&lt;T&gt; list，Comparator&lt;? super T&gt; )</code>方法灵活的完成，这个里面就涉及到了Comparator这个接口，位于位于java.util包下，排序是comparator能实现的功能之一,该接口代表一个比较器，比较器具有可比性！顾名思义就是做排序的，通俗地讲需要比较两个对象谁排在前谁排在后，那么比较的方法就是：</p><ul><li><p><code> public int compare(String o1, String o2)</code>：比较其两个参数的顺序。</p><blockquote><p>两个对象比较的结果有三种：大于，等于，小于。</p><p>如果要按照升序排序，<br>则o1 小于o2，返回（负数），相等返回0，01大于02返回（正数）<br>如果要按照降序排序<br>则o1 小于o2，返回（正数），相等返回0，01大于02返回（负数）</p></blockquote></li></ul><p>操作如下:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CollectionsDemo3</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        ArrayList&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">        list.add(<span class="string">&quot;cba&quot;</span>);</span><br><span class="line">        list.add(<span class="string">&quot;aba&quot;</span>);</span><br><span class="line">        list.add(<span class="string">&quot;sba&quot;</span>);</span><br><span class="line">        list.add(<span class="string">&quot;nba&quot;</span>);</span><br><span class="line">        <span class="comment">//排序方法  按照第一个单词的降序</span></span><br><span class="line">        Collections.sort(list, <span class="keyword">new</span> Comparator&lt;String&gt;() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(String o1, String o2)</span> </span>&#123;</span><br><span class="line">                <span class="keyword">return</span> o2.charAt(<span class="number">0</span>) - o1.charAt(<span class="number">0</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        System.out.println(list);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[sba, nba, cba, aba]</span><br></pre></td></tr></table></figure><h2 id="2-3-简述Comparable和Comparator两个接口的区别。"><a href="#2-3-简述Comparable和Comparator两个接口的区别。" class="headerlink" title="2.3 简述Comparable和Comparator两个接口的区别。"></a>2.3 简述Comparable和Comparator两个接口的区别。</h2><p><strong>Comparable</strong>：强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序，类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次，不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表（和数组）可以通过Collections.sort（和Arrays.sort）进行自动排序，对象可以用作有序映射中的键或有序集合中的元素，无需指定比较器。</p><p><strong>Comparator</strong>强行对某个对象进行整体排序。可以将Comparator 传递给sort方法（如Collections.sort或 Arrays.sort），从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构（如有序set或有序映射）的顺序，或者为那些没有自然顺序的对象collection提供排序。</p><h2 id="2-4-练习"><a href="#2-4-练习" class="headerlink" title="2.4  练习"></a>2.4  练习</h2><p>创建一个学生类，存储到ArrayList集合中完成指定排序操作。</p><p>Student 初始类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Student</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">(String name, <span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">        <span class="keyword">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAge</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAge</span><span class="params">(<span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Student&#123;&quot;</span> +</span><br><span class="line">               <span class="string">&quot;name=&#x27;&quot;</span> + name + <span class="string">&#x27;\&#x27;&#x27;</span> +</span><br><span class="line">               <span class="string">&quot;, age=&quot;</span> + age +</span><br><span class="line">               <span class="string">&#x27;&#125;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建四个学生对象 存储到集合中</span></span><br><span class="line">        ArrayList&lt;Student&gt; list = <span class="keyword">new</span> ArrayList&lt;Student&gt;();</span><br><span class="line"></span><br><span class="line">        list.add(<span class="keyword">new</span> Student(<span class="string">&quot;rose&quot;</span>,<span class="number">18</span>));</span><br><span class="line">        list.add(<span class="keyword">new</span> Student(<span class="string">&quot;jack&quot;</span>,<span class="number">16</span>));</span><br><span class="line">        list.add(<span class="keyword">new</span> Student(<span class="string">&quot;abc&quot;</span>,<span class="number">16</span>));</span><br><span class="line">        list.add(<span class="keyword">new</span> Student(<span class="string">&quot;ace&quot;</span>,<span class="number">17</span>));</span><br><span class="line">        list.add(<span class="keyword">new</span> Student(<span class="string">&quot;mark&quot;</span>,<span class="number">16</span>));</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">          让学生 按照年龄排序 升序</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line"><span class="comment">//        Collections.sort(list);//要求 该list中元素类型  必须实现比较器Comparable接口</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (Student student : list) &#123;</span><br><span class="line">            System.out.println(student);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>发现，当我们调用Collections.sort()方法的时候 程序报错了。</p><p>原因：如果想要集合中的元素完成排序，那么必须要实现比较器Comparable接口。</p><p>于是我们就完成了Student类的一个实现，如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Student</span> <span class="keyword">implements</span> <span class="title">Comparable</span>&lt;<span class="title">Student</span>&gt;</span>&#123;</span><br><span class="line">    ....</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compareTo</span><span class="params">(Student o)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.age-o.age;<span class="comment">//升序</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>再次测试，代码就OK 了效果如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Student&#123;name=<span class="string">&#x27;jack&#x27;</span>, age=<span class="number">16</span>&#125;</span><br><span class="line">Student&#123;name=<span class="string">&#x27;abc&#x27;</span>, age=<span class="number">16</span>&#125;</span><br><span class="line">Student&#123;name=<span class="string">&#x27;mark&#x27;</span>, age=<span class="number">16</span>&#125;</span><br><span class="line">Student&#123;name=<span class="string">&#x27;ace&#x27;</span>, age=<span class="number">17</span>&#125;</span><br><span class="line">Student&#123;name=<span class="string">&#x27;rose&#x27;</span>, age=<span class="number">18</span>&#125;</span><br></pre></td></tr></table></figure><h2 id="2-5-扩展"><a href="#2-5-扩展" class="headerlink" title="2.5 扩展"></a>2.5 扩展</h2><p>如果在使用的时候，想要独立的定义规则去使用 可以采用Collections.sort(List list,Comparetor<T> c)方式，自己定义规则：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Collections.sort(list, <span class="keyword">new</span> Comparator&lt;Student&gt;() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(Student o1, Student o2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> o2.getAge()-o1.getAge();<span class="comment">//以学生的年龄降序</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Student&#123;name&#x3D;&#39;rose&#39;, age&#x3D;18&#125;</span><br><span class="line">Student&#123;name&#x3D;&#39;ace&#39;, age&#x3D;17&#125;</span><br><span class="line">Student&#123;name&#x3D;&#39;jack&#39;, age&#x3D;16&#125;</span><br><span class="line">Student&#123;name&#x3D;&#39;abc&#39;, age&#x3D;16&#125;</span><br><span class="line">Student&#123;name&#x3D;&#39;mark&#39;, age&#x3D;16&#125;</span><br></pre></td></tr></table></figure><p>如果想要规则更多一些，可以参考下面代码：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Collections.sort(list, <span class="keyword">new</span> Comparator&lt;Student&gt;() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(Student o1, Student o2)</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 年龄降序</span></span><br><span class="line">                <span class="keyword">int</span> result = o2.getAge()-o1.getAge();<span class="comment">//年龄降序</span></span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span>(result==<span class="number">0</span>)&#123;<span class="comment">//第一个规则判断完了 下一个规则 姓名的首字母 升序</span></span><br><span class="line">                    result = o1.getName().charAt(<span class="number">0</span>)-o2.getName().charAt(<span class="number">0</span>);</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> result;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br></pre></td></tr></table></figure><p>效果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Student&#123;name&#x3D;&#39;rose&#39;, age&#x3D;18&#125;</span><br><span class="line">Student&#123;name&#x3D;&#39;ace&#39;, age&#x3D;17&#125;</span><br><span class="line">Student&#123;name&#x3D;&#39;abc&#39;, age&#x3D;16&#125;</span><br><span class="line">Student&#123;name&#x3D;&#39;jack&#39;, age&#x3D;16&#125;</span><br><span class="line">Student&#123;name&#x3D;&#39;mark&#39;, age&#x3D;16&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记08-Map详解</title>
      <link href="java/javase/note/note08/"/>
      <url>java/javase/note/note08/</url>
      
        <content type="html"><![CDATA[<h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li> Map集合</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><ul><li><input checked="" disabled="" type="checkbox"> 能够说出Map集合特点</li><li><input disabled="" type="checkbox"> 使用Map集合添加方法保存数据</li><li><input checked="" disabled="" type="checkbox"> 使用”键找值”的方式遍历Map集合</li><li><input checked="" disabled="" type="checkbox"> 使用”键值对”的方式遍历Map集合</li><li><input disabled="" type="checkbox"> 能够使用HashMap存储自定义键值对的数据</li><li><input disabled="" type="checkbox"> 能够使用HashMap编写斗地主洗牌发牌案例</li></ul><h1 id="第一章-Map集合"><a href="#第一章-Map集合" class="headerlink" title="第一章 Map集合"></a>第一章 Map集合</h1><h2 id="1-1-概述"><a href="#1-1-概述" class="headerlink" title="1.1 概述"></a>1.1 概述</h2><p>现实生活中，我们常会看到这样的一种集合：IP地址与主机名，身份证号与个人，系统用户名与系统用户对象等，这种一一对应的关系，就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象，即<code>java.util.Map</code>接口</p><p>我们通过查看<code>Map</code>接口描述，发现<code>Map</code>接口下的集合与<code>Collection</code>接口下的集合，它们存储数据的形式不同，如下图。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5CCollection%E4%B8%8EMap.bmp"></p><ul><li><code>Collection</code>中的集合，元素是孤立存在的（理解为单身），向集合中存储元素采用一个个元素的方式存储。</li><li><code>Map</code>中的集合，元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成，通过键可以找对所对应的值。</li><li><code>Collection</code>中的集合称为单列集合，<code>Map</code>中的集合称为双列集合。</li><li>需要注意的是，<code>Map</code>中的集合不能包含重复的键，值可以重复；每个键只能对应一个值。</li></ul><h2 id="1-2-Map常用子类"><a href="#1-2-Map常用子类" class="headerlink" title="1.2  Map常用子类"></a>1.2  Map常用子类</h2><p>通过查看Map接口描述，看到Map有多个子类，这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。</p><ul><li>**HashMap&lt;K,V&gt;**：存储数据采用的哈希表结构，元素的存取顺序不能保证一致。由于要保证键的唯一、不重复，需要重写键的hashCode()方法、equals()方法。</li><li>**LinkedHashMap&lt;K,V&gt;**：HashMap下有个子类LinkedHashMap，存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致；通过哈希表结构可以保证的键的唯一、不重复，需要重写键的hashCode()方法、equals()方法。</li></ul><blockquote><p>tips：Map接口中的集合都有两个泛型变量&lt;K,V&gt;,在使用时，要为两个泛型变量赋予数据类型。两个泛型变量&lt;K,V&gt;的数据类型可以相同，也可以不同。</p></blockquote><h2 id="1-3-Map接口中的常用方法"><a href="#1-3-Map接口中的常用方法" class="headerlink" title="1.3  Map接口中的常用方法"></a>1.3  Map接口中的常用方法</h2><p>Map接口中定义了很多方法，常用的如下：</p><ul><li><code>public V put(K key, V value)</code>:  把指定的键与指定的值添加到Map集合中。</li><li><code>public V remove(Object key)</code>: 把指定的键 所对应的键值对元素 在Map集合中删除，返回被删除元素的值。</li><li><code>public V get(Object key)</code> 根据指定的键，在Map集合中获取对应的值。</li><li><code>boolean containsKey(Object key)  </code> 判断集合中是否包含指定的键。</li><li><code>public Set&lt;K&gt; keySet()</code>: 获取Map集合中所有的键，存储到Set集合中。</li><li><code>public Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet()</code>: 获取到Map集合中所有的键值对对象的集合(Set集合)。</li></ul><p>Map接口的方法演示</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MapDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//创建 map对象</span></span><br><span class="line">        HashMap&lt;String, String&gt;  map = <span class="keyword">new</span> HashMap&lt;String, String&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//添加元素到集合</span></span><br><span class="line">        map.put(<span class="string">&quot;黄晓明&quot;</span>, <span class="string">&quot;杨颖&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;文章&quot;</span>, <span class="string">&quot;马伊琍&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;邓超&quot;</span>, <span class="string">&quot;孙俪&quot;</span>);</span><br><span class="line">        System.out.println(map);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//String remove(String key)</span></span><br><span class="line">        System.out.println(map.remove(<span class="string">&quot;邓超&quot;</span>));</span><br><span class="line">        System.out.println(map);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 想要查看 黄晓明的媳妇 是谁</span></span><br><span class="line">        System.out.println(map.get(<span class="string">&quot;黄晓明&quot;</span>));</span><br><span class="line">        System.out.println(map.get(<span class="string">&quot;邓超&quot;</span>));    </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>tips:</p><p>使用put方法时，若指定的键(key)在集合中没有，则没有这个键对应的值，返回null，并把指定的键值添加到集合中； </p><p>若指定的键(key)在集合中存在，则返回值为集合中键对应的值（该值为替换前的值），并把指定键所对应的值，替换成指定的新值。 </p></blockquote><h2 id="1-4-Map集合遍历键找值方式"><a href="#1-4-Map集合遍历键找值方式" class="headerlink" title="1.4   Map集合遍历键找值方式"></a>1.4   Map集合遍历键找值方式</h2><p>键找值方式：即通过元素中的键，获取键所对应的值</p><p>分析步骤：</p><ol><li>获取Map中所有的键，由于键是唯一的，所以返回一个Set集合存储所有的键。方法提示:<code>keyset()</code></li><li>遍历键的Set集合，得到每一个键。</li><li>根据键，获取键所对应的值。方法提示:<code>get(K key)</code></li></ol><p>代码演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MapDemo01</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//创建Map集合对象 </span></span><br><span class="line">        HashMap&lt;String, String&gt; map = <span class="keyword">new</span> HashMap&lt;String,String&gt;();</span><br><span class="line">        <span class="comment">//添加元素到集合 </span></span><br><span class="line">        map.put(<span class="string">&quot;胡歌&quot;</span>, <span class="string">&quot;霍建华&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;郭德纲&quot;</span>, <span class="string">&quot;于谦&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;薛之谦&quot;</span>, <span class="string">&quot;大张伟&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//获取所有的键  获取键集</span></span><br><span class="line">        Set&lt;String&gt; keys = map.keySet();</span><br><span class="line">        <span class="comment">// 遍历键集 得到 每一个键</span></span><br><span class="line">        <span class="keyword">for</span> (String key : keys) &#123;</span><br><span class="line">            <span class="comment">//key  就是键</span></span><br><span class="line">            <span class="comment">//获取对应值</span></span><br><span class="line">            String value = map.get(key);</span><br><span class="line">            System.out.println(key+<span class="string">&quot;的CP是：&quot;</span>+value);</span><br><span class="line">        &#125;  </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>遍历图解：</p><p><img src= "/img/loading.gif" data-lazy-src="img%5CMap%E9%9B%86%E5%90%88%E9%81%8D%E5%8E%86%E6%96%B9%E5%BC%8F%E4%B8%80.bmp"></p><h2 id="1-5-Entry键值对对象"><a href="#1-5-Entry键值对对象" class="headerlink" title="1.5  Entry键值对对象"></a>1.5  Entry键值对对象</h2><p>我们已经知道，<code>Map</code>中存放的是两种对象，一种称为<strong>key</strong>(键)，一种称为<strong>value</strong>(值)，它们在在<code>Map</code>中是一一对应关系，这一对对象又称做<code>Map</code>中的一个<code>Entry(项)</code>。<code>Entry</code>将键值对的对应关系封装成了对象。即键值对对象，这样我们在遍历<code>Map</code>集合时，就可以从每一个键值对（<code>Entry</code>）对象中获取对应的键与对应的值。</p><p> 既然Entry表示了一对键和值，那么也同样提供了获取对应键和对应值得方法：</p><ul><li><code>public K getKey()</code>：获取Entry对象中的键。</li><li><code>public V getValue()</code>：获取Entry对象中的值。</li></ul><p>在Map集合中也提供了获取所有Entry对象的方法：</p><ul><li><code>public Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet()</code>: 获取到Map集合中所有的键值对对象的集合(Set集合)。</li></ul><h2 id="1-6-Map集合遍历键值对方式"><a href="#1-6-Map集合遍历键值对方式" class="headerlink" title="1.6 Map集合遍历键值对方式"></a>1.6 Map集合遍历键值对方式</h2><p>键值对方式：即通过集合中每个键值对(Entry)对象，获取键值对(Entry)对象中的键与值。</p><p>操作步骤与图解：</p><ol><li><p> 获取Map集合中，所有的键值对(Entry)对象，以Set集合形式返回。方法提示:<code>entrySet()</code>。</p></li><li><p> 遍历包含键值对(Entry)对象的Set集合，得到每一个键值对(Entry)对象。</p></li><li><p> 通过键值对(Entry)对象，获取Entry对象中的键与值。  方法提示:<code>getkey() getValue()</code>     </p></li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MapDemo02</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建Map集合对象 </span></span><br><span class="line">        HashMap&lt;String, String&gt; map = <span class="keyword">new</span> HashMap&lt;String,String&gt;();</span><br><span class="line">        <span class="comment">// 添加元素到集合 </span></span><br><span class="line">        map.put(<span class="string">&quot;胡歌&quot;</span>, <span class="string">&quot;霍建华&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;郭德纲&quot;</span>, <span class="string">&quot;于谦&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;薛之谦&quot;</span>, <span class="string">&quot;大张伟&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 获取 所有的 entry对象  entrySet</span></span><br><span class="line">        Set&lt;Entry&lt;String,String&gt;&gt; entrySet = map.entrySet();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 遍历得到每一个entry对象</span></span><br><span class="line">        <span class="keyword">for</span> (Entry&lt;String, String&gt; entry : entrySet) &#123;</span><br><span class="line">            <span class="comment">// 解析 </span></span><br><span class="line">            String key = entry.getKey();</span><br><span class="line">            String value = entry.getValue();  </span><br><span class="line">            System.out.println(key+<span class="string">&quot;的CP是:&quot;</span>+value);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>遍历图解：</p><p><img src= "/img/loading.gif" data-lazy-src="img%5CMap%E9%9B%86%E5%90%88%E9%81%8D%E5%8E%86%E6%96%B9%E5%BC%8F%E4%BA%8C.bmp"></p><blockquote><p>tips：Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了。</p></blockquote><h2 id="1-7-HashMap存储自定义类型键值"><a href="#1-7-HashMap存储自定义类型键值" class="headerlink" title="1.7  HashMap存储自定义类型键值"></a>1.7  HashMap存储自定义类型键值</h2><p>练习：每位学生（姓名，年龄）都有自己的家庭住址。那么，既然有对应关系，则将学生对象和家庭住址存储到map集合中。学生作为键, 家庭住址作为值。</p><blockquote><p>注意，学生姓名相同并且年龄相同视为同一名学生。</p></blockquote><p>编写学生类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Student</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">(String name, <span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">        <span class="keyword">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAge</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAge</span><span class="params">(<span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object o)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span> == o)</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        <span class="keyword">if</span> (o == <span class="keyword">null</span> || getClass() != o.getClass())</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        Student student = (Student) o;</span><br><span class="line">        <span class="keyword">return</span> age == student.age &amp;&amp; Objects.equals(name, student.name);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hashCode</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> Objects.hash(name, age);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编写测试类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HashMapTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//1,创建Hashmap集合对象。</span></span><br><span class="line">        Map&lt;Student,String&gt;map = <span class="keyword">new</span> HashMap&lt;Student,String&gt;();</span><br><span class="line">        <span class="comment">//2,添加元素。</span></span><br><span class="line">        map.put(newStudent(<span class="string">&quot;lisi&quot;</span>,<span class="number">28</span>), <span class="string">&quot;上海&quot;</span>);</span><br><span class="line">        map.put(newStudent(<span class="string">&quot;wangwu&quot;</span>,<span class="number">22</span>), <span class="string">&quot;北京&quot;</span>);</span><br><span class="line">        map.put(newStudent(<span class="string">&quot;zhaoliu&quot;</span>,<span class="number">24</span>), <span class="string">&quot;成都&quot;</span>);</span><br><span class="line">        map.put(newStudent(<span class="string">&quot;zhouqi&quot;</span>,<span class="number">25</span>), <span class="string">&quot;广州&quot;</span>);</span><br><span class="line">        map.put(newStudent(<span class="string">&quot;wangwu&quot;</span>,<span class="number">22</span>), <span class="string">&quot;南京&quot;</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">//3,取出元素。键找值方式</span></span><br><span class="line">        Set&lt;Student&gt;keySet = map.keySet();</span><br><span class="line">        <span class="keyword">for</span>(Student key: keySet)&#123;</span><br><span class="line">            Stringvalue = map.get(key);</span><br><span class="line">            System.out.println(key.toString()+<span class="string">&quot;.....&quot;</span>+value);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>当给HashMap中存放自定义对象时，如果自定义对象作为key存在，这时要保证对象唯一，必须复写对象的hashCode和equals方法(如果忘记，请回顾HashSet存放自定义对象)。</li><li>如果要保证map中存放的key和取出的顺序一致，可以使用<code>java.util.LinkedHashMap</code>集合来存放。</li></ul><h2 id="1-8-LinkedHashMap"><a href="#1-8-LinkedHashMap" class="headerlink" title="1.8   LinkedHashMap"></a>1.8   LinkedHashMap</h2><p>我们知道HashMap保证成对元素唯一，并且查询速度很快，可是成对元素存放进去是没有顺序的，那么我们要保证有序，还要速度快怎么办呢？</p><p>在HashMap下面有一个子类LinkedHashMap，它是链表和哈希表组合的一个数据存储结构。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LinkedHashMapDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        LinkedHashMap&lt;String, String&gt; map = <span class="keyword">new</span> LinkedHashMap&lt;String, String&gt;();</span><br><span class="line">        map.put(<span class="string">&quot;邓超&quot;</span>, <span class="string">&quot;孙俪&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;李晨&quot;</span>, <span class="string">&quot;范冰冰&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;刘德华&quot;</span>, <span class="string">&quot;朱丽倩&quot;</span>);</span><br><span class="line">        Set&lt;Entry&lt;String, String&gt;&gt; entrySet = map.entrySet();</span><br><span class="line">        <span class="keyword">for</span> (Entry&lt;String, String&gt; entry : entrySet) &#123;</span><br><span class="line">            System.out.println(entry.getKey() + <span class="string">&quot;  &quot;</span> + entry.getValue());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>结果:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">邓超  孙俪</span><br><span class="line">李晨  范冰冰</span><br><span class="line">刘德华  朱丽倩</span><br></pre></td></tr></table></figure><h2 id="1-9-Map集合练习"><a href="#1-9-Map集合练习" class="headerlink" title="1.9 Map集合练习"></a>1.9 Map集合练习</h2><p><strong>需求：</strong></p><p>计算一个字符串中每个字符出现次数。</p><p><strong>分析：</strong></p><ol><li> 获取一个字符串对象</li><li> 创建一个Map集合，键代表字符，值代表次数。</li><li> 遍历字符串得到每个字符。</li><li> 判断Map中是否有该键。</li><li> 如果没有，第一次出现，存储次数为1；如果有，则说明已经出现过，获取到对应的值进行++，再次存储。     </li><li> 打印最终结果</li></ol><p><strong>代码：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MapTest</span> </span>&#123;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//友情提示</span></span><br><span class="line">        System.out.println(<span class="string">&quot;请录入一个字符串:&quot;</span>);</span><br><span class="line">        String line = <span class="keyword">new</span> Scanner(System.in).nextLine();</span><br><span class="line">        <span class="comment">// 定义 每个字符出现次数的方法</span></span><br><span class="line">        findChar(line);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">findChar</span><span class="params">(String line)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//1:创建一个集合 存储  字符 以及其出现的次数</span></span><br><span class="line">        HashMap&lt;Character, Integer&gt; map = <span class="keyword">new</span> HashMap&lt;Character, Integer&gt;();</span><br><span class="line">        <span class="comment">//2:遍历字符串</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; line.length(); i++) &#123;</span><br><span class="line">            <span class="keyword">char</span> c = line.charAt(i);</span><br><span class="line">            <span class="comment">//判断 该字符 是否在键集中</span></span><br><span class="line">            <span class="keyword">if</span> (!map.containsKey(c)) &#123;<span class="comment">//说明这个字符没有出现过</span></span><br><span class="line">                <span class="comment">//那就是第一次</span></span><br><span class="line">                map.put(c, <span class="number">1</span>);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">//先获取之前的次数</span></span><br><span class="line">                Integer count = map.get(c);</span><br><span class="line">                <span class="comment">//count++;</span></span><br><span class="line">                <span class="comment">//再次存入  更新</span></span><br><span class="line">                map.put(c, ++count);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(map);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第二章-补充知识点"><a href="#第二章-补充知识点" class="headerlink" title="第二章 补充知识点"></a>第二章 补充知识点</h1><h2 id="2-1-JDK9对集合添加的优化"><a href="#2-1-JDK9对集合添加的优化" class="headerlink" title="2.1  JDK9对集合添加的优化"></a>2.1  JDK9对集合添加的优化</h2><p>通常，我们在代码中创建一个集合（例如，List 或 Set ），并直接用一些元素填充它。 实例化集合，几个 add方法 调用，使得代码重复。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        List&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        list.add(<span class="string">&quot;abc&quot;</span>);</span><br><span class="line">        list.add(<span class="string">&quot;def&quot;</span>);</span><br><span class="line">        list.add(<span class="string">&quot;ghi&quot;</span>);</span><br><span class="line">        System.out.println(list);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p> Java 9，添加了几种集合工厂方法,更方便创建少量元素的集合、map实例。新的List、Set、Map的静态工厂方法可以更方便地创建集合的不可变实例。</p><p>例子：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HelloJDK9</span> </span>&#123;  </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;  </span><br><span class="line">        Set&lt;String&gt; str1=Set.of(<span class="string">&quot;a&quot;</span>,<span class="string">&quot;b&quot;</span>,<span class="string">&quot;c&quot;</span>);  </span><br><span class="line">        <span class="comment">//str1.add(&quot;c&quot;);这里编译的时候不会错，但是执行的时候会报错，因为是不可变的集合  </span></span><br><span class="line">        System.out.println(str1);  </span><br><span class="line">        Map&lt;String,Integer&gt; str2=Map.of(<span class="string">&quot;a&quot;</span>,<span class="number">1</span>,<span class="string">&quot;b&quot;</span>,<span class="number">2</span>);  </span><br><span class="line">        System.out.println(str2);  </span><br><span class="line">        List&lt;String&gt; str3=List.of(<span class="string">&quot;a&quot;</span>,<span class="string">&quot;b&quot;</span>);  </span><br><span class="line">        System.out.println(str3);  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>需要注意以下两点：</p><blockquote><p>1:of()方法只是Map，List，Set这三个接口的静态方法，其父类接口和子类实现并没有这类方法，比如    HashSet，ArrayList等待；</p><p>2:返回的集合是不可变的；</p></blockquote><h2 id="2-2-Debug追踪"><a href="#2-2-Debug追踪" class="headerlink" title="2.2 Debug追踪"></a>2.2 Debug追踪</h2><p><strong>使用IDEA的断点调试功能，查看程序的运行过程</strong></p><ol><li><p>在有效代码行，点击行号右边的空白区域，设置断点，程序执行到断点将停止，我们可以手动来运行程序   </p><p>   <img src= "/img/loading.gif" data-lazy-src="img/debug1.png"></p></li><li><p>点击Debug运行模式       <img src= "/img/loading.gif" data-lazy-src="img%5Cdebug2.png">                                                                                                                                                                      </p></li><li><p>程序停止在断点上不再执行，而IDEA最下方打开了Debug调试窗口  </p><p>  <img src= "/img/loading.gif" data-lazy-src="img%5Cdebug3.png"><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug4.png"></p></li><li><p>Debug调试窗口介绍</p><p> <img src= "/img/loading.gif" data-lazy-src="img%5Cdebug5.png"></p></li><li><p>快捷键F8，代码向下执行一行,第九行执行完毕，执行到第10行（第10行还未执行）</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug6.png"></p></li><li><p>切换到控制台面板，控制台显示 请录入一个字符串： 并且等待键盘录入</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug7.png"></p></li><li><p>快捷键F8，程序继续向后执行，执行键盘录入操作，在控制台录入数据 ababcea</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug8.png"></p><p>回车之后效果：<img src= "/img/loading.gif" data-lazy-src="img%5Cdebug9.png"></p><p>调试界面效果：<img src= "/img/loading.gif" data-lazy-src="img%5Cdebug0.png"></p></li><li><p>此时到达findChar方法，快捷键F7，进入方法findChar</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug11.png"></p></li><li><p>快捷键F8 接续执行，创建了map对象，变量区域显示</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug12.png"></p></li><li><p>快捷键F8 接续执行，进入到循环中，循环变量i为 0,F8再继续执行，就获取到变量c赋值为字符‘a’ 字节值97</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug13.png"></p></li><li><p>快捷键F8 接续执行，进入到判断语句中，因为该字符 不在Map集合键集中，再按F8执行，进入该判断中</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug14.png"></p></li><li><p>快捷键F8 接续执行，循环结束，进入下次循环，此时map中已经添加一对儿元素</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug15.png"></p></li><li><p>快捷键F8 接续执行，进入下次循环，再继续上面的操作，我们就可以看到代码每次是如何执行的了</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug16.png"></p></li><li><p>如果不想继续debug,那么可以使用快捷键F9,程序正常执行到结束，程序结果在控制台显示</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cdebug17.png"></p></li></ol><h1 id="第三章-模拟斗地主洗牌发牌"><a href="#第三章-模拟斗地主洗牌发牌" class="headerlink" title="第三章  模拟斗地主洗牌发牌"></a>第三章  模拟斗地主洗牌发牌</h1><h2 id="3-1-案例介绍"><a href="#3-1-案例介绍" class="headerlink" title="3.1 案例介绍"></a>3.1 案例介绍</h2><p>按照斗地主的规则，完成洗牌发牌的动作。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E6%96%97%E5%9C%B0%E4%B8%BB.png"></p><p>具体规则：</p><ol><li>组装54张扑克牌将</li><li>54张牌顺序打乱</li><li>三个玩家参与游戏，三人交替摸牌，每人17张牌，最后三张留作底牌。</li><li>查看三人各自手中的牌（按照牌的大小排序）、底牌</li></ol><blockquote><p>规则：手中扑克牌从大到小的摆放顺序：大王,小王,2,A,K,Q,J,10,9,8,7,6,5,4,3</p></blockquote><h2 id="3-2-案例需求分析"><a href="#3-2-案例需求分析" class="headerlink" title="3.2 案例需求分析"></a>3.2 案例需求分析</h2><ol><li> 准备牌：</li></ol><p>完成数字与纸牌的映射关系：</p><p>使用双列Map(HashMap)集合，完成一个数字与字符串纸牌的对应关系(相当于一个字典)。</p><ol start="2"><li> 洗牌：</li></ol><p>通过数字完成洗牌发牌</p><ol start="3"><li> 发牌：</li></ol><p>将每个人以及底牌设计为ArrayList<String>,将最后3张牌直接存放于底牌，剩余牌通过对3取模依次发牌。</p><p>存放的过程中要求数字大小与斗地主规则的大小对应。</p><p>将代表不同纸牌的数字分配给不同的玩家与底牌。</p><ol start="4"><li> 看牌：</li></ol><p>通过Map集合找到对应字符展示。</p><p>通过查询纸牌与数字的对应关系，由数字转成纸牌字符串再进行展示。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E6%96%97%E5%9C%B0%E4%B8%BB%E5%88%86%E6%9E%90.png"></p><h2 id="3-3-实现代码步骤"><a href="#3-3-实现代码步骤" class="headerlink" title="3.3  实现代码步骤"></a>3.3  实现代码步骤</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Poker</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">         * 1组装54张扑克牌</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">// 1.1 创建Map集合存储</span></span><br><span class="line">        HashMap&lt;Integer, String&gt; pokerMap = <span class="keyword">new</span> HashMap&lt;Integer, String&gt;();</span><br><span class="line">        <span class="comment">// 1.2 创建 花色集合 与 数字集合</span></span><br><span class="line">        ArrayList&lt;String&gt; colors = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">        ArrayList&lt;String&gt; numbers = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 1.3 存储 花色 与数字</span></span><br><span class="line">        Collections.addAll(colors, <span class="string">&quot;♦&quot;</span>, <span class="string">&quot;♣&quot;</span>, <span class="string">&quot;♥&quot;</span>, <span class="string">&quot;♠&quot;</span>);</span><br><span class="line">        Collections.addAll(numbers, <span class="string">&quot;2&quot;</span>, <span class="string">&quot;A&quot;</span>, <span class="string">&quot;K&quot;</span>, <span class="string">&quot;Q&quot;</span>, <span class="string">&quot;J&quot;</span>, <span class="string">&quot;10&quot;</span>, <span class="string">&quot;9&quot;</span>, <span class="string">&quot;8&quot;</span>, <span class="string">&quot;7&quot;</span>, <span class="string">&quot;6&quot;</span>, <span class="string">&quot;5&quot;</span>, <span class="string">&quot;4&quot;</span>, <span class="string">&quot;3&quot;</span>);</span><br><span class="line">        <span class="comment">// 设置 存储编号变量</span></span><br><span class="line">        <span class="keyword">int</span> count = <span class="number">1</span>;</span><br><span class="line">        pokerMap.put(count++, <span class="string">&quot;大王&quot;</span>);</span><br><span class="line">        pokerMap.put(count++, <span class="string">&quot;小王&quot;</span>);</span><br><span class="line">        <span class="comment">// 1.4 创建牌 存储到map集合中</span></span><br><span class="line">        <span class="keyword">for</span> (String number : numbers) &#123;</span><br><span class="line">            <span class="keyword">for</span> (String color : colors) &#123;</span><br><span class="line">                String card = color + number;</span><br><span class="line">                pokerMap.put(count++, card);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">         * 2 将54张牌顺序打乱</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">// 取出编号 集合</span></span><br><span class="line">        Set&lt;Integer&gt; numberSet = pokerMap.keySet();</span><br><span class="line">        <span class="comment">// 因为要将编号打乱顺序 所以 应该先进行转换到 list集合中</span></span><br><span class="line">        ArrayList&lt;Integer&gt; numberList = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">        numberList.addAll(numberSet);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 打乱顺序</span></span><br><span class="line">        Collections.shuffle(numberList);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3 完成三个玩家交替摸牌，每人17张牌，最后三张留作底牌</span></span><br><span class="line">        <span class="comment">// 3.1 发牌的编号</span></span><br><span class="line">        <span class="comment">// 创建三个玩家编号集合 和一个 底牌编号集合</span></span><br><span class="line">        ArrayList&lt;Integer&gt; noP1 = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">        ArrayList&lt;Integer&gt; noP2 = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">        ArrayList&lt;Integer&gt; noP3 = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">        ArrayList&lt;Integer&gt; dipaiNo = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3.2发牌的编号</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; numberList.size(); i++) &#123;</span><br><span class="line">            <span class="comment">// 获取该编号</span></span><br><span class="line">            Integer no = numberList.get(i);</span><br><span class="line">            <span class="comment">// 发牌</span></span><br><span class="line">            <span class="comment">// 留出底牌</span></span><br><span class="line">            <span class="keyword">if</span> (i &gt;= <span class="number">51</span>) &#123;</span><br><span class="line">                dipaiNo.add(no);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (i % <span class="number">3</span> == <span class="number">0</span>) &#123;</span><br><span class="line">                    noP1.add(no);</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (i % <span class="number">3</span> == <span class="number">1</span>) &#123;</span><br><span class="line">                    noP2.add(no);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    noP3.add(no);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 4 查看三人各自手中的牌（按照牌的大小排序）、底牌</span></span><br><span class="line">        <span class="comment">// 4.1 对手中编号进行排序</span></span><br><span class="line">        Collections.sort(noP1);</span><br><span class="line">        Collections.sort(noP2);</span><br><span class="line">        Collections.sort(noP3);</span><br><span class="line">        Collections.sort(dipaiNo);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 4.2 进行牌面的转换</span></span><br><span class="line">        <span class="comment">// 创建三个玩家牌面集合 以及底牌牌面集合</span></span><br><span class="line">        ArrayList&lt;String&gt; player1 = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">        ArrayList&lt;String&gt; player2 = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">        ArrayList&lt;String&gt; player3 = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">        ArrayList&lt;String&gt; dipai = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 4.3转换</span></span><br><span class="line">        <span class="keyword">for</span> (Integer i : noP1) &#123;</span><br><span class="line">            <span class="comment">// 4.4 根据编号找到 牌面 pokerMap</span></span><br><span class="line">            String card = pokerMap.get(i);</span><br><span class="line">            <span class="comment">// 添加到对应的 牌面集合中</span></span><br><span class="line">            player1.add(card);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (Integer i : noP2) &#123;</span><br><span class="line">            String card = pokerMap.get(i);</span><br><span class="line">            player2.add(card);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (Integer i : noP3) &#123;</span><br><span class="line">            String card = pokerMap.get(i);</span><br><span class="line">            player3.add(card);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (Integer i : dipaiNo) &#123;</span><br><span class="line">            String card = pokerMap.get(i);</span><br><span class="line">            dipai.add(card);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//4.5 查看</span></span><br><span class="line">        System.out.println(<span class="string">&quot;令狐冲：&quot;</span>+player1);</span><br><span class="line">        System.out.println(<span class="string">&quot;石破天：&quot;</span>+player2);</span><br><span class="line">        System.out.println(<span class="string">&quot;鸠摩智：&quot;</span>+player3);</span><br><span class="line">        System.out.println(<span class="string">&quot;底牌：&quot;</span>+dipai);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记09-【继承、super、this、抽象类】</title>
      <link href="java/javase/note/note09/"/>
      <url>java/javase/note/note09/</url>
      
        <content type="html"><![CDATA[<h1 id="目录"><a href="#目录" class="headerlink" title="目录"></a>目录</h1><h3 id="今日内容"><a href="#今日内容" class="headerlink" title="今日内容"></a>今日内容</h3><ul><li>三大特性- 继承 </li><li>方法重写</li><li>super关键字</li><li>this关键字</li><li>抽象类</li></ul><h3 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h3>  <li>基本概念    <ol>      <li>当多个类之间有相同的特征和行为时，可以将相同的内容提取出来组成一个公共类，让多个公共类吸收公共类中已有特征和行为而在多个类的内部编写自己独有特征和行为的方式，叫做继承</li>      <li>使用继承可以提高代码的复用性和扩展性以及可维护性</li>      <li>在Java语言中使用extends( 扩展)关键字来表达继承关系        <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">如：</span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Student</span> <span class="kd">extends</span> <span class="nc">Person</span><span class="o">&#123;&#125;</span><span class="err">表示</span><span class="n">Student</span><span class="err">类继承自</span><span class="n">Person</span><span class="err">类</span><span class="err">其中</span><span class="n">Person</span><span class="err">类叫做基类、父类、超类</span><span class="err">其中</span><span class="n">Student</span><span class="err">类叫做派生类、子类、孩子类</span></code></pre></div>        </div>      </li>    </ol>  </li>  <li>注意事项    <ol>      <li>子类可以继承父类的成员变量和成员方法，其中私有成员变量可以继承但不可以直接使用。子类不可以继承父类的构造方法和私有方法</li>      <li>无论使用何种方式构造子类对象时，都会自动调用父类中的无参构造方法来初始化从父类继承下来的成员变量，相当于在子类构造方法的第一行增加代码:super()的效果        <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">以后写代码一律带着</span><span class="kd">super</span><span class="o">()</span><span class="err">格式写</span><span class="err">如：</span><span class="kd">public</span> <span class="nf">Worker</span><span class="o">()&#123;</span> <span class="kd">super</span><span class="o">();</span> <span class="o">&#125;</span><span class="kd">public</span> <span class="nf">Worker</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">,</span><span class="kt">int</span> <span class="n">age</span><span class="o">,</span><span class="kt">int</span> <span class="n">salary</span><span class="o">)&#123;</span> <span class="kd">super</span><span class="o">(</span><span class="n">name</span><span class="o">,</span><span class="n">age</span><span class="o">);</span> <span class="n">setSalary</span><span class="o">(</span><span class="n">salary</span><span class="o">);</span> <span class="o">&#125;</span>  </code></pre></div>        </div>      </li>      <li>使用继承必须满足 子类is a父类 的逻辑关系，也就是不能滥用继承</li>      <li>Java语言中只支持单继承，不支持多继承，也就是一个子类只能有一个父类，但一个父类可以有多个子类</li>    </ol>  </li>    <h3 id="方法重写"><a href="#方法重写" class="headerlink" title="方法重写"></a>方法重写</h3>  <li>方法重写    <ol>      <li>基本概念：当父类中继承下来的方法不满足子类的需求时，就需要在子类中重新写一个与父类中一样的方法来覆盖从父类中继承的版本，这种方式就叫做重写</li>      <li>重写的原则：        <ol>          <li>方法名相同，参数列表相同，返回值类型相同，从jdk1.5开始允许返回子类类型</li>          <li>要求方法访问权限不能变小，可以相同或者变大</li>          <li>不能抛出更大的异常</li>        </ol>      </li>      <li>语法格式        <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Override</span><span class="kd">public</span> <span class="kt">void</span> <span class="nf">show</span><span class="o">()&#123;</span> <span class="kd">super</span><span class="o">.</span><span class="na">show</span><span class="o">();</span> <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"我一个月能挣"</span><span class="o">+</span><span class="n">getSalary</span><span class="o">()+</span><span class="s">"呢"</span><span class="o">);</span><span class="o">&#125;</span></code></pre></div>        </div>      </li>    </ol>  </li><h3 id="方法重载"><a href="#方法重载" class="headerlink" title="方法重载"></a>方法重载</h3><li>方法重载(Overload 会用即可)    <ol>      <li>基本概念：在Java语言中若方法名称相同但参数列表不同，这样的方法构成方法重载</li>      <li>体现形式：方法重载的主要形式有：参数的个数不同、参数的类型不同、参数的顺序不同，与形参变量名和返回值类型无关，但建议返回值类型最好相同</li>      <li>实际意义：对于调用者来说只需要记住一个方法名就可以调用各种不同的版本实现不同的效果</li>    </ol>  </li>    ### this关键字  <li>基本概念    <ol>      <li>在构造方法中，this关键字代表当前正在构造的对象</li>      <li>在成员方法中，this关键字代表当前正在调用的对象</li>    </ol>  </li>  <li>使用方式    <ol>      <li>当形参变量和成员变量同名时，在构造方法或成员方法中通常优先使用形参变量，若希望使用成员变量就需要在变量名的前面加上this.进行说明(重中之重)</li>      <li>在构造方法的第一行使用this(实参)的方式可以调用本类中的其他构造方法(了解)</li>    </ol>  </li><h3 id="抽象类"><a href="#抽象类" class="headerlink" title="抽象类"></a>抽象类</h3><ol>  <li>抽象方法的概念：抽象方法就是指不能具体实现的方法，也就是没有方法体并使用abstract关键字修饰    <ol>      <li>语法格式        <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">访问控制符</span> <span class="kd">abstract</span> <span class="err">返回值类型</span> <span class="err">方法名称</span><span class="o">(</span><span class="err">形参列表</span><span class="o">);</span><span class="err">如：</span><span class="kd">public</span> <span class="kd">abstract</span> <span class="kt">void</span> <span class="nf">cry</span><span class="o">();</span></code></pre></div>        </div>      </li>    </ol>  </li>  <li>抽象类的概念：不能具体实例化的类，也就是不能创建对象并使用abstract的类</li>  <li>注意事项    <ol>      <li>抽象类中可以有成员变量，构造方法以及成员方法</li>      <li>抽象类中可以有抽象方法也可以没有抽象方法</li>      <li>拥有抽象方法的类必须是抽象类，因此严格来说，具有抽象方法并使用abstract关键字修饰的类才算真正意义上的抽象类</li>    </ol>  </li>  <li>实际意义    <ol>      <li>抽象类的意义不在于自身创建对象而在于被继承，当一个类继承抽象类后必须重写抽象类中的抽象方法，否则该类也变成抽象类</li>      <li>也就是说抽象类对子类具有强制性和规范性，因此叫做模板设计模式</li>    </ol>  </li>  <li>经验分享    <ol>      <li>在以后的开发中推荐使用多态的语法格式，当父类的引用指向子类对象时，那么父类引用直接调用的所有方法一定是父类拥有的方法，若希望更换子类时，只需要将new关键字后面的类型修改而其他地方无需更改立即生效，从而提高了代码的可维护性。</li>      <li>缺点是：父类引用不能直接访问子类独有的方法，若访问则需要强转</li>    </ol>  </li></ol><h3 id="笔试题考点"><a href="#笔试题考点" class="headerlink" title="笔试题考点"></a>笔试题考点</h3><ol>  <li>请问abstract和final关键字能不能共同修饰一个方法？</li>  <li>答：不能，abstract修饰的方法是一个抽象方法，抽象方法是没有方法体的，它本身没有意义。它的意义体现在被继承和被重写。而final修饰的方法不能被重写，所以他俩不能共存</li>  <li>请问abstract和static关键字能不能共同修饰一个方法？</li>  <li>答：不能，abstract关键字不能创建对象的意义在于防止不小心调用抽象方法，而static将它体到类层级，可以直接通过类名调用，也就失去了本来的意义</li>  <li>请问abstract和private关键字能不能共同修饰一个方法？</li>  <li>答：不能，abstract修饰的方法是一个抽象方法，抽象方法是没有方法体的，它本身没有意义。它的意义体现在被继承和被重写。而private修饰的方法不能被继承，所以他俩不能共存</li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中Collection类数据</title>
      <link href="java/javaold/java-Collection/"/>
      <url>java/javaold/java-Collection/</url>
      
        <content type="html"><![CDATA[<h2 id="Collection集合"><a href="#Collection集合" class="headerlink" title="Collection集合"></a>Collection集合</h2><h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><h4 id="集合和数组可不一样"><a href="#集合和数组可不一样" class="headerlink" title="集合和数组可不一样:"></a>集合和数组可不一样:</h4><ul><li>数组的长度的固定的,集合可以随时增删改查</li><li>数组的数据类型的相同的基本数据类型,而集合存储的是不同类型的对象</li></ul><h4 id="集合的分类"><a href="#集合的分类" class="headerlink" title="集合的分类"></a>集合的分类</h4><p>集合按照其存储结构可以分为两大类，分别是单列集合<code>java.util.Collection</code>和双列集合<code>java.util.Map</code></p><h4 id="Collection单列集合"><a href="#Collection单列集合" class="headerlink" title="Collection单列集合"></a>Collection单列集合</h4><ul><li><strong>Collection</strong>：单列集合类的根接口，用于存储一系列符合某种规则的元素，它有两个重要的子接口，分别是<code>java.util.List</code>和<code>java.util.Set</code>。</li></ul><p>其中，<code>List</code>的特点是元素有序、元素可重复。</p><p><code>Set</code>的特点是元素无序，而且不可重复。</p><p><code>List</code>接口的主要实现类有<code>java.util.ArrayList</code>和<code>java.util.LinkedList</code>，</p><p><code>Set</code>接口的主要实现类有<code>java.util.HashSet</code>和<code>java.util.TreeSet</code>。</p><h4 id="Collection-常用功能"><a href="#Collection-常用功能" class="headerlink" title="Collection 常用功能"></a>Collection 常用功能</h4><p>Collection是所有单列集合的父接口，因此在Collection中定义了单列集合(List和Set)通用的一些方法，这些方法可用于操作所有的单列集合。方法如下：</p><ul><li><code>public boolean add(E e)</code>：  把给定的对象添加到当前集合中。</li><li><code>public void clear()</code> :清空集合中所有的元素。</li><li><code>public boolean remove(E e)</code>: 把给定的对象在当前集合中删除。</li><li><code>public boolean contains(E e)</code>: 判断当前集合中是否包含给定的对象。</li><li><code>public boolean isEmpty()</code>: 判断当前集合是否为空。</li><li><code>public int size()</code>: 返回集合中元素的个数。</li><li><code>public Object[] toArray()</code>: 把集合中的元素，存储到数组中。</li></ul><h2 id="list"><a href="#list" class="headerlink" title="list"></a>list</h2><h3 id="list集合"><a href="#list集合" class="headerlink" title="list集合"></a>list集合</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">List作为Collection集合的子接口，不但继承了Collection接口中的全部方法，而且还增加了一些根据元素索引来操</span><br><span class="line">作集合的特有方法，如下：</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(<span class="keyword">int</span> index, E element)</span> : 将指定的元素，添加到该集合中的指定位置上。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">get</span><span class="params">(<span class="keyword">int</span> index)</span> :返回集合中指定位置的元素。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">remove</span><span class="params">(<span class="keyword">int</span> index)</span> : 移除列表中指定位置的元素, 返回的是被移除的元素。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">set</span><span class="params">(<span class="keyword">int</span> index, E element)</span> :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。</span></span><br></pre></td></tr></table></figure><h3 id="ArrayList集合"><a href="#ArrayList集合" class="headerlink" title="ArrayList集合"></a>ArrayList集合</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">实际开发中对一个集合元素的添加与删除经常涉及到首尾操作，而LinkedList提供了大量首尾操作的方法。这些方</span><br><span class="line">法我们作为了解即可：</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addFirst</span><span class="params">(E e)</span> :将指定元素插入此列表的开头。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addLast</span><span class="params">(E e)</span> :将指定元素添加到此列表的结尾。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">getFirst</span><span class="params">()</span> :返回此列表的第一个元素。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">getLast</span><span class="params">()</span> :返回此列表的最后一个元素。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">removeFirst</span><span class="params">()</span> :移除并返回此列表的第一个元素。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">removeLast</span><span class="params">()</span> :移除并返回此列表的最后一个元素。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> E <span class="title">pop</span><span class="params">()</span> :从此列表所表示的堆栈处弹出一个元素。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">push</span><span class="params">(E e)</span> :将元素推入此列表所表示的堆栈。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isEmpty</span><span class="params">()</span> ：如果列表不包含元素，则返回<span class="keyword">true</span></span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记05【Object类、常用API】-笔记</title>
      <link href="java/javase/note/note05/"/>
      <url>java/javase/note/note05/</url>
      
        <content type="html"><![CDATA[<h1 id="day01【Object类、常用API】"><a href="#day01【Object类、常用API】" class="headerlink" title="day01【Object类、常用API】"></a>day01【Object类、常用API】</h1><h2 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h2><ul><li>Object类</li><li>Date类</li><li>DateFormat类</li><li>Calendar类</li><li>System类</li><li>StringBuilder类</li><li>包装类</li></ul><h2 id="教学目标"><a href="#教学目标" class="headerlink" title="教学目标"></a>教学目标</h2><p>-[ ] 能够说出Object类的特点<br>-[ ] 能够重写Object类的toString方法<br>-[ ] 能够重写Object类的equals方法<br>-[ ] 能够使用日期类输出当前日期<br>-[ ] 能够使用将日期格式化为字符串的方法<br>-[ ] 能够使用将字符串转换成日期的方法<br>-[ ] 能够使用System类的数组复制方法<br>-[ ] 能够使用System类获取当前毫秒时刻值<br>-[ ] 能够说出使用StringBuilder类可以解决的问题<br>-[ ] 能够使用StringBuilder进行字符串拼接操作<br>-[ ] 能够说出8种基本类型对应的包装类名称<br>-[ ] 能够说出自动装箱、自动拆箱的概念<br>-[ ] 能够将字符串转换为对应的基本类型<br>-[ ] 能够将基本类型转换为对应的字符串</p><h1 id="第一章-Object类"><a href="#第一章-Object类" class="headerlink" title="第一章 Object类"></a>第一章 Object类</h1><h2 id="1-1-概述"><a href="#1-1-概述" class="headerlink" title="1.1 概述"></a>1.1 概述</h2><p><code>java.lang.Object</code>类是Java语言中的根类，即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候，最终找的父类就是Object。</p><p>如果一个类没有特别指定父类，    那么默认则继承自Object类。例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyClass</span> /*<span class="keyword">extends</span> <span class="title">Object</span>*/ </span>&#123;</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>根据JDK源代码及Object类的API文档，Object类当中包含的方法有11个。今天我们主要学习其中的2个：</p><ul><li><code>public String toString()</code>：返回该对象的字符串表示。</li><li><code>public boolean equals(Object obj)</code>：指示其他某个对象是否与此对象“相等”。</li></ul><h2 id="1-2-toString方法"><a href="#1-2-toString方法" class="headerlink" title="1.2 toString方法"></a>1.2 toString方法</h2><h3 id="方法摘要"><a href="#方法摘要" class="headerlink" title="方法摘要"></a>方法摘要</h3><ul><li><code>public String toString()</code>：返回该对象的字符串表示。</li></ul><p>toString方法返回该对象的字符串表示，其实该字符串内容就是对象的类型+@+内存地址值。</p><p>由于toString方法返回的结果是内存地址，而在开发中，经常需要按照对象的属性得到相应的字符串表现形式，因此也需要重写它。</p><h3 id="覆盖重写"><a href="#覆盖重写" class="headerlink" title="覆盖重写"></a>覆盖重写</h3><p>如果不希望使用toString方法的默认行为，则可以对它进行覆盖重写。例如自定义的Person类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123;  </span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Person&#123;&quot;</span> + <span class="string">&quot;name=&#x27;&quot;</span> + name + <span class="string">&#x27;\&#x27;&#x27;</span> + <span class="string">&quot;, age=&quot;</span> + age + <span class="string">&#x27;&#125;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 省略构造器与Getter Setter</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在IntelliJ IDEA中，可以点击<code>Code</code>菜单中的<code>Generate...</code>，也可以使用快捷键<code>alt+insert</code>，点击<code>toString()</code>选项。选择需要包含的成员变量并确定。如下图所示：</p><p><img src= "/img/loading.gif" data-lazy-src="img%5CtoString%E6%96%B9%E6%B3%95%E7%9A%84%E8%87%AA%E5%8A%A8%E9%87%8D%E5%86%99.bmp" alt="toString方法的自动重写"></p><blockquote><p>小贴士： 在我们直接使用输出语句输出对象名的时候,其实通过该对象调用了其toString()方法。</p></blockquote><h2 id="1-3-equals方法"><a href="#1-3-equals方法" class="headerlink" title="1.3 equals方法"></a>1.3 equals方法</h2><h3 id="方法摘要-1"><a href="#方法摘要-1" class="headerlink" title="方法摘要"></a>方法摘要</h3><ul><li><code>public boolean equals(Object obj)</code>：指示其他某个对象是否与此对象“相等”。</li></ul><p>调用成员方法equals并指定参数为另一个对象，则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。</p><h3 id="默认地址比较"><a href="#默认地址比较" class="headerlink" title="默认地址比较"></a>默认地址比较</h3><p>如果没有覆盖重写equals方法，那么Object类中默认进行<code>==</code>运算符的对象地址比较，只要不是同一个对象，结果必然为false。</p><h3 id="对象内容比较"><a href="#对象内容比较" class="headerlink" title="对象内容比较"></a>对象内容比较</h3><p>如果希望进行对象的内容比较，即所有或指定的部分成员变量相同就判定两个对象相同，则可以覆盖重写equals方法。例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Objects;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line"><span class="keyword">private</span> String name;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object o)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 如果对象地址一样，则认为相同</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span> == o)</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        <span class="comment">// 如果参数为空，或者类型信息不一样，则认为不同</span></span><br><span class="line">        <span class="keyword">if</span> (o == <span class="keyword">null</span> || getClass() != o.getClass())</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        <span class="comment">// 转换为当前类型</span></span><br><span class="line">        Person person = (Person) o;</span><br><span class="line">        <span class="comment">// 要求基本类型相等，并且将引用类型交给java.util.Objects类的equals静态方法取用结果</span></span><br><span class="line">        <span class="keyword">return</span> age == person.age &amp;&amp; Objects.equals(name, person.name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这段代码充分考虑了对象为空、类型一致等问题，但方法内容并不唯一。大多数IDE都可以自动生成equals方法的代码内容。在IntelliJ IDEA中，可以使用<code>Code</code>菜单中的<code>Generate…</code>选项，也可以使用快捷键<code>alt+insert</code>，并选择<code>equals() and hashCode()</code>进行自动代码生成。如下图所示：</p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cequals%E6%96%B9%E6%B3%951.png"></p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cequals%E6%96%B9%E6%B3%952.png"></p><p><img src= "/img/loading.gif" data-lazy-src="img%5Cequals%E6%96%B9%E6%B3%953.png"></p><blockquote><p>tips：Object类当中的hashCode等其他方法，今后学习。</p></blockquote><h2 id="1-4-Objects类"><a href="#1-4-Objects类" class="headerlink" title="1.4 Objects类"></a>1.4 Objects类</h2><p>在刚才IDEA自动重写equals代码中，使用到了<code>java.util.Objects</code>类，那么这个类是什么呢？</p><p>在<strong>JDK7</strong>添加了一个Objects工具类，它提供了一些方法来操作对象，它由一些静态的实用方法组成，这些方法是null-save（空指针安全的）或null-tolerant（容忍空指针的），用于计算对象的hashcode、返回对象的字符串表示形式、比较两个对象。</p><p>在比较两个对象的时候，Object的equals方法容易抛出空指针异常，而Objects类中的equals方法就优化了这个问题。方法如下：</p><ul><li><code>public static boolean equals(Object a, Object b)</code>:判断两个对象是否相等。</li></ul><p>我们可以查看一下源码，学习一下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object a, Object b)</span> </span>&#123;  </span><br><span class="line">    <span class="keyword">return</span> (a == b) || (a != <span class="keyword">null</span> &amp;&amp; a.equals(b));  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第二章-日期时间类"><a href="#第二章-日期时间类" class="headerlink" title="第二章 日期时间类"></a>第二章 日期时间类</h1><h2 id="2-1-Date类"><a href="#2-1-Date类" class="headerlink" title="2.1 Date类"></a>2.1 Date类</h2><h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p><code> java.util.Date</code>类 表示特定的瞬间，精确到毫秒。</p><p>继续查阅Date类的描述，发现Date拥有多个构造函数，只是部分已经过时，但是其中有未过时的构造函数可以把毫秒值转成日期对象。</p><ul><li><code>public Date()</code>：分配Date对象并初始化此对象，以表示分配它的时间（精确到毫秒）。</li><li><code>public Date(long date)</code>：分配Date对象并初始化此对象，以表示自从标准基准时间（称为“历元（epoch）”，即1970年1月1日00:00:00 GMT）以来的指定毫秒数。</li></ul><blockquote><p>tips: 由于我们处于东八区，所以我们的基准时间为1970年1月1日8时0分0秒。</p></blockquote><p>简单来说：使用无参构造，可以自动设置当前系统时间的毫秒时刻；指定long类型的构造参数，可以自定义毫秒时刻。例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01Date</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建日期对象，把当前的时间</span></span><br><span class="line">        System.out.println(<span class="keyword">new</span> Date()); <span class="comment">// Tue Jan 16 14:37:35 CST 2018</span></span><br><span class="line">        <span class="comment">// 创建日期对象，把当前的毫秒值转成日期对象</span></span><br><span class="line">        System.out.println(<span class="keyword">new</span> Date(<span class="number">0L</span>)); <span class="comment">// Thu Jan 01 08:00:00 CST 1970</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>tips:在使用println方法时，会自动调用Date类中的toString方法。Date类对Object类中的toString方法进行了覆盖重写，所以结果为指定格式的字符串。</p></blockquote><h3 id="常用方法"><a href="#常用方法" class="headerlink" title="常用方法"></a>常用方法</h3><p>Date类中的多数方法已经过时，常用的方法有：</p><ul><li><code>public long getTime()</code> 把日期对象转换成对应的时间毫秒值。</li></ul><h2 id="2-2-DateFormat类"><a href="#2-2-DateFormat类" class="headerlink" title="2.2 DateFormat类"></a>2.2 DateFormat类</h2><p><code>java.text.DateFormat</code> 是日期/时间格式化子类的抽象类，我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。</p><ul><li><strong>格式化</strong>：按照指定的格式，从Date对象转换为String对象。</li><li><strong>解析</strong>：按照指定的格式，从String对象转换为Date对象。</li></ul><h3 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h3><p>由于DateFormat为抽象类，不能直接使用，所以需要常用的子类<code>java.text.SimpleDateFormat</code>。这个类需要一个模式（格式）来指定格式化或解析的标准。构造方法为：</p><ul><li><code>public SimpleDateFormat(String pattern)</code>：用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。</li></ul><p>参数pattern是一个字符串，代表日期时间的自定义格式。</p><h3 id="格式规则"><a href="#格式规则" class="headerlink" title="格式规则"></a>格式规则</h3><p>常用的格式规则为：</p><table><thead><tr><th>标识字母（区分大小写）</th><th>含义</th></tr></thead><tbody><tr><td>y</td><td>年</td></tr><tr><td>M</td><td>月</td></tr><tr><td>d</td><td>日</td></tr><tr><td>H</td><td>时</td></tr><tr><td>m</td><td>分</td></tr><tr><td>s</td><td>秒</td></tr></tbody></table><blockquote><p>备注：更详细的格式规则，可以参考SimpleDateFormat类的API文档0。</p></blockquote><p>创建SimpleDateFormat对象的代码如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.text.DateFormat;</span><br><span class="line"><span class="keyword">import</span> java.text.SimpleDateFormat;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo02SimpleDateFormat</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 对应的日期格式如：2018-01-16 15:06:38</span></span><br><span class="line">        DateFormat format = <span class="keyword">new</span> SimpleDateFormat(<span class="string">&quot;yyyy-MM-dd HH:mm:ss&quot;</span>);</span><br><span class="line">    &#125;    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="常用方法-1"><a href="#常用方法-1" class="headerlink" title="常用方法"></a>常用方法</h3><p>DateFormat类的常用方法有：</p><ul><li><code>public String format(Date date)</code>：将Date对象格式化为字符串。</li><li><code>public Date parse(String source)</code>：将字符串解析为Date对象。</li></ul><h4 id="format方法"><a href="#format方法" class="headerlink" title="format方法"></a>format方法</h4><p>使用format方法的代码为：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.text.DateFormat;</span><br><span class="line"><span class="keyword">import</span> java.text.SimpleDateFormat;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> 把Date对象转换成String</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo03DateFormatMethod</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Date date = <span class="keyword">new</span> Date();</span><br><span class="line">        <span class="comment">// 创建日期格式化对象,在获取格式化对象时可以指定风格</span></span><br><span class="line">        DateFormat df = <span class="keyword">new</span> SimpleDateFormat(<span class="string">&quot;yyyy年MM月dd日&quot;</span>);</span><br><span class="line">        String str = df.format(date);</span><br><span class="line">        System.out.println(str); <span class="comment">// 2008年1月23日</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="parse方法"><a href="#parse方法" class="headerlink" title="parse方法"></a>parse方法</h4><p>使用parse方法的代码为：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.text.DateFormat;</span><br><span class="line"><span class="keyword">import</span> java.text.ParseException;</span><br><span class="line"><span class="keyword">import</span> java.text.SimpleDateFormat;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> 把String转换成Date对象</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo04DateFormatMethod</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ParseException </span>&#123;</span><br><span class="line">        DateFormat df = <span class="keyword">new</span> SimpleDateFormat(<span class="string">&quot;yyyy年MM月dd日&quot;</span>);</span><br><span class="line">        String str = <span class="string">&quot;2018年12月11日&quot;</span>;</span><br><span class="line">        Date date = df.parse(str);</span><br><span class="line">        System.out.println(date); <span class="comment">// Tue Dec 11 00:00:00 CST 2018</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="2-3-练习"><a href="#2-3-练习" class="headerlink" title="2.3 练习"></a>2.3 练习</h2><p>请使用日期时间相关的API，计算出一个人已经出生了多少天。</p><p><strong>思路：</strong></p><p>1.获取当前时间对应的毫秒值</p><p>2.获取自己出生日期对应的毫秒值</p><p>3.两个时间相减（当前时间– 出生日期）</p><p><strong>代码实现：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">function</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">System.out.println(<span class="string">&quot;请输入出生日期 格式 YYYY-MM-dd&quot;</span>);</span><br><span class="line"><span class="comment">// 获取出生日期,键盘输入</span></span><br><span class="line">String birthdayString = <span class="keyword">new</span> Scanner(System.in).next();</span><br><span class="line"><span class="comment">// 将字符串日期,转成Date对象</span></span><br><span class="line"><span class="comment">// 创建SimpleDateFormat对象,写日期模式</span></span><br><span class="line">SimpleDateFormat sdf = <span class="keyword">new</span> SimpleDateFormat(<span class="string">&quot;yyyy-MM-dd&quot;</span>);</span><br><span class="line"><span class="comment">// 调用方法parse,字符串转成日期对象</span></span><br><span class="line">Date birthdayDate = sdf.parse(birthdayString);</span><br><span class="line"><span class="comment">// 获取今天的日期对象</span></span><br><span class="line">Date todayDate = <span class="keyword">new</span> Date();</span><br><span class="line"><span class="comment">// 将两个日期转成毫秒值,Date类的方法getTime</span></span><br><span class="line"><span class="keyword">long</span> birthdaySecond = birthdayDate.getTime();</span><br><span class="line"><span class="keyword">long</span> todaySecond = todayDate.getTime();</span><br><span class="line"><span class="keyword">long</span> secone = todaySecond-birthdaySecond;</span><br><span class="line"><span class="keyword">if</span> (secone &lt; <span class="number">0</span>)&#123;</span><br><span class="line">System.out.println(<span class="string">&quot;还没出生呢&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">System.out.println(secone/<span class="number">1000</span>/<span class="number">60</span>/<span class="number">60</span>/<span class="number">24</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="2-4-Calendar类"><a href="#2-4-Calendar类" class="headerlink" title="2.4 Calendar类"></a>2.4 Calendar类</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>日历我们都见过</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C%E6%97%A5%E5%8E%86.jpg"></p><p><code>java.util.Calendar</code>是日历类，在Date后出现，替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量，方便获取。日历类就是方便获取各个时间属性的。</p><h3 id="获取方式"><a href="#获取方式" class="headerlink" title="获取方式"></a>获取方式</h3><p>Calendar为抽象类，由于语言敏感性，Calendar类在创建对象时并非直接创建，而是通过静态方法创建，返回子类对象，如下：</p><p>Calendar静态方法</p><ul><li><code>public static Calendar getInstance()</code>：使用默认时区和语言环境获得一个日历</li></ul><p>例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Calendar;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo06CalendarInit</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Calendar cal = Calendar.getInstance();</span><br><span class="line">    &#125;    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="常用方法-2"><a href="#常用方法-2" class="headerlink" title="常用方法"></a>常用方法</h3><p>根据Calendar类的API文档，常用方法有：</p><ul><li><code>public int get(int field)</code>：返回给定日历字段的值。</li><li><code>public void set(int field, int value)</code>：将给定的日历字段设置为给定值。</li><li><code>public abstract void add(int field, int amount)</code>：根据日历的规则，为给定的日历字段添加或减去指定的时间量。</li><li><code>public Date getTime()</code>：返回一个表示此Calendar时间值（从历元到现在的毫秒偏移量）的Date对象。</li></ul><p>Calendar类中提供很多成员常量，代表给定的日历字段：</p><table><thead><tr><th>字段值</th><th>含义</th></tr></thead><tbody><tr><td>YEAR</td><td>年</td></tr><tr><td>MONTH</td><td>月（从0开始，可以+1使用）</td></tr><tr><td>DAY_OF_MONTH</td><td>月中的天（几号）</td></tr><tr><td>HOUR</td><td>时（12小时制）</td></tr><tr><td>HOUR_OF_DAY</td><td>时（24小时制）</td></tr><tr><td>MINUTE</td><td>分</td></tr><tr><td>SECOND</td><td>秒</td></tr><tr><td>DAY_OF_WEEK</td><td>周中的天（周几，周日为1，可以-1使用）</td></tr></tbody></table><h4 id="get-set方法"><a href="#get-set方法" class="headerlink" title="get/set方法"></a>get/set方法</h4><p>get方法用来获取指定字段的值，set方法用来设置指定字段的值，代码使用演示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Calendar;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CalendarUtil</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建Calendar对象</span></span><br><span class="line">        Calendar cal = Calendar.getInstance();</span><br><span class="line">        <span class="comment">// 设置年 </span></span><br><span class="line">        <span class="keyword">int</span> year = cal.get(Calendar.YEAR);</span><br><span class="line">        <span class="comment">// 设置月</span></span><br><span class="line">        <span class="keyword">int</span> month = cal.get(Calendar.MONTH) + <span class="number">1</span>;</span><br><span class="line">        <span class="comment">// 设置日</span></span><br><span class="line">        <span class="keyword">int</span> dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);</span><br><span class="line">        System.out.print(year + <span class="string">&quot;年&quot;</span> + month + <span class="string">&quot;月&quot;</span> + dayOfMonth + <span class="string">&quot;日&quot;</span>);</span><br><span class="line">    &#125;    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Calendar;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo07CalendarMethod</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Calendar cal = Calendar.getInstance();</span><br><span class="line">        cal.set(Calendar.YEAR, <span class="number">2020</span>);</span><br><span class="line">        System.out.print(year + <span class="string">&quot;年&quot;</span> + month + <span class="string">&quot;月&quot;</span> + dayOfMonth + <span class="string">&quot;日&quot;</span>); <span class="comment">// 2020年1月17日</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="add方法"><a href="#add方法" class="headerlink" title="add方法"></a>add方法</h4><p>add方法可以对指定日历字段的值进行加减操作，如果第二个参数为正数则加上偏移量，如果为负数则减去偏移量。代码如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Calendar;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo08CalendarMethod</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Calendar cal = Calendar.getInstance();</span><br><span class="line">        System.out.print(year + <span class="string">&quot;年&quot;</span> + month + <span class="string">&quot;月&quot;</span> + dayOfMonth + <span class="string">&quot;日&quot;</span>); <span class="comment">// 2018年1月17日</span></span><br><span class="line">        <span class="comment">// 使用add方法</span></span><br><span class="line">        cal.add(Calendar.DAY_OF_MONTH, <span class="number">2</span>); <span class="comment">// 加2天</span></span><br><span class="line">        cal.add(Calendar.YEAR, -<span class="number">3</span>); <span class="comment">// 减3年</span></span><br><span class="line">        System.out.print(year + <span class="string">&quot;年&quot;</span> + month + <span class="string">&quot;月&quot;</span> + dayOfMonth + <span class="string">&quot;日&quot;</span>); <span class="comment">// 2015年1月18日; </span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="getTime方法"><a href="#getTime方法" class="headerlink" title="getTime方法"></a>getTime方法</h4><p>Calendar中的getTime方法并不是获取毫秒时刻，而是拿到对应的Date对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Calendar;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo09CalendarMethod</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Calendar cal = Calendar.getInstance();</span><br><span class="line">        Date date = cal.getTime();</span><br><span class="line">        System.out.println(date); <span class="comment">// Tue Jan 16 16:03:09 CST 2018</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>小贴士：</p><p>​     西方星期的开始为周日，中国为周一。</p><p>​     在Calendar类中，月份的表示是以0-11代表1-12月。</p><p>​     日期是有大小关系的，时间靠后，时间越大。</p></blockquote><h1 id="第三章-System类"><a href="#第三章-System类" class="headerlink" title="第三章 System类"></a>第三章 System类</h1><p><code>java.lang.System</code>类中提供了大量的静态方法，可以获取与系统相关的信息或系统级操作，在System类的API文档中，常用的方法有：</p><ul><li><code>public static long currentTimeMillis()</code>：返回以毫秒为单位的当前时间。</li><li><code>public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)</code>：将数组中指定的数据拷贝到另一个数组中。</li></ul><h2 id="3-1-currentTimeMillis方法"><a href="#3-1-currentTimeMillis方法" class="headerlink" title="3.1 currentTimeMillis方法"></a>3.1 currentTimeMillis方法</h2><p>实际上，currentTimeMillis方法就是 获取当前系统时间与1970年01月01日00:00点之间的毫秒差值</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SystemDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">       <span class="comment">//获取当前时间毫秒值</span></span><br><span class="line">        System.out.println(System.currentTimeMillis()); <span class="comment">// 1516090531144</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="练习"><a href="#练习" class="headerlink" title="练习"></a>练习</h3><p>验证for循环打印数字1-9999所需要使用的时间（毫秒）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SystemTest1</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">long</span> start = System.currentTimeMillis();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10000</span>; i++) &#123;</span><br><span class="line">            System.out.println(i);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">long</span> end = System.currentTimeMillis();</span><br><span class="line">        System.out.println(<span class="string">&quot;共耗时毫秒：&quot;</span> + (end - start));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-2-arraycopy方法"><a href="#3-2-arraycopy方法" class="headerlink" title="3.2 arraycopy方法"></a>3.2 arraycopy方法</h2><ul><li><code>public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)</code>：将数组中指定的数据拷贝到另一个数组中。</li></ul><p>数组的拷贝动作是系统级的，性能很高。System.arraycopy方法具有5个参数，含义分别为：</p><table><thead><tr><th>参数序号</th><th>参数名称</th><th>参数类型</th><th>参数含义</th></tr></thead><tbody><tr><td>1</td><td>src</td><td>Object</td><td>源数组</td></tr><tr><td>2</td><td>srcPos</td><td>int</td><td>源数组索引起始位置</td></tr><tr><td>3</td><td>dest</td><td>Object</td><td>目标数组</td></tr><tr><td>4</td><td>destPos</td><td>int</td><td>目标数组索引起始位置</td></tr><tr><td>5</td><td>length</td><td>int</td><td>复制元素个数</td></tr></tbody></table><h3 id="练习-1"><a href="#练习-1" class="headerlink" title="练习"></a>练习</h3><p>将src数组中前3个元素，复制到dest数组的前3个位置上复制元素前：src数组元素[1,2,3,4,5]，dest数组元素[6,7,8,9,10]复制元素后：src数组元素[1,2,3,4,5]，dest数组元素[1,2,3,9,10]</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo11SystemArrayCopy</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] src = <span class="keyword">new</span> <span class="keyword">int</span>[]&#123;<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>&#125;;</span><br><span class="line">        <span class="keyword">int</span>[] dest = <span class="keyword">new</span> <span class="keyword">int</span>[]&#123;<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>,<span class="number">10</span>&#125;;</span><br><span class="line">        System.arraycopy( src, <span class="number">0</span>, dest, <span class="number">0</span>, <span class="number">3</span>);</span><br><span class="line">        <span class="comment">/*代码运行后：两个数组中的元素发生了变化</span></span><br><span class="line"><span class="comment">         src数组元素[1,2,3,4,5]</span></span><br><span class="line"><span class="comment">         dest数组元素[1,2,3,9,10]</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第四章-StringBuilder类"><a href="#第四章-StringBuilder类" class="headerlink" title="第四章 StringBuilder类"></a>第四章 StringBuilder类</h1><h2 id="4-1-字符串拼接问题"><a href="#4-1-字符串拼接问题" class="headerlink" title="4.1 字符串拼接问题"></a>4.1 字符串拼接问题</h2><p>由于String类的对象内容不可改变，所以每当进行字符串拼接时，总是会在内存中创建一个新的对象。例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">StringDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String s = <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line">        s += <span class="string">&quot;World&quot;</span>;</span><br><span class="line">        System.out.println(s);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在API中对String类有这样的描述：字符串是常量，它们的值在创建后不能被更改。</p><p>根据这句话分析我们的代码，其实总共产生了三个字符串，即<code>&quot;Hello&quot;</code>、<code>&quot;World&quot;</code>和<code>&quot;HelloWorld&quot;</code>。引用变量s首先指向<code>Hello</code>对象，最终指向拼接出来的新字符串对象，即<code>HelloWord</code> 。</p><p><img src= "/img/loading.gif" data-lazy-src="img%5CString%E6%8B%BC%E6%8E%A5%E9%97%AE%E9%A2%98.bmp"></p><p>由此可知，如果对字符串进行拼接操作，每次拼接，都会构建一个新的String对象，既耗时，又浪费空间。为了解决这一问题，可以使用<code>java.lang.StringBuilder</code>类。</p><h2 id="4-2-StringBuilder概述"><a href="#4-2-StringBuilder概述" class="headerlink" title="4.2 StringBuilder概述"></a>4.2 StringBuilder概述</h2><p>查阅<code>java.lang.StringBuilder</code>的API，StringBuilder又称为可变字符序列，它是一个类似于 String 的字符串缓冲区，通过某些方法调用可以改变该序列的长度和内容。</p><p>原来StringBuilder是个字符串的缓冲区，即它是一个容器，容器中可以装很多字符串。并且能够对其中的字符串进行各种操作。</p><p>它的内部拥有一个数组用来存放字符串内容，进行字符串拼接时，直接在数组中加入新内容。StringBuilder会自动维护数组的扩容。原理如下图所示：(默认16字符空间，超过自动扩充)</p><p><img src= "/img/loading.gif" data-lazy-src="img%5C06-StringBuilder%E7%9A%84%E5%8E%9F%E7%90%86.png" alt="06-StringBuilder的原理"></p><h2 id="4-3-构造方法"><a href="#4-3-构造方法" class="headerlink" title="4.3 构造方法"></a>4.3 构造方法</h2><p>根据StringBuilder的API文档，常用构造方法有2个：</p><ul><li><code>public StringBuilder()</code>：构造一个空的StringBuilder容器。</li><li><code>public StringBuilder(String str)</code>：构造一个StringBuilder容器，并将字符串添加进去。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">StringBuilderDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        StringBuilder sb1 = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">        System.out.println(sb1); <span class="comment">// (空白)</span></span><br><span class="line">        <span class="comment">// 使用带参构造</span></span><br><span class="line">        StringBuilder sb2 = <span class="keyword">new</span> StringBuilder(<span class="string">&quot;itcast&quot;</span>);</span><br><span class="line">        System.out.println(sb2); <span class="comment">// itcast</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="4-4-常用方法"><a href="#4-4-常用方法" class="headerlink" title="4.4 常用方法"></a>4.4 常用方法</h2><p>StringBuilder常用的方法有2个：</p><ul><li><code>public StringBuilder append(...)</code>：添加任意类型数据的字符串形式，并返回当前对象自身。</li><li><code>public String toString()</code>：将当前StringBuilder对象转换为String对象。</li></ul><h3 id="append方法"><a href="#append方法" class="headerlink" title="append方法"></a>append方法</h3><p>append方法具有多种重载形式，可以接收任意类型的参数。任何数据作为参数都会将对应的字符串内容添加到StringBuilder中。例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo02StringBuilder</span> </span>&#123;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="comment">//创建对象</span></span><br><span class="line">StringBuilder builder = <span class="keyword">new</span> StringBuilder();</span><br><span class="line"><span class="comment">//public StringBuilder append(任意类型)</span></span><br><span class="line">StringBuilder builder2 = builder.append(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line"><span class="comment">//对比一下</span></span><br><span class="line">System.out.println(<span class="string">&quot;builder:&quot;</span>+builder);</span><br><span class="line">System.out.println(<span class="string">&quot;builder2:&quot;</span>+builder2);</span><br><span class="line">System.out.println(builder == builder2); <span class="comment">//true</span></span><br><span class="line">    <span class="comment">// 可以添加 任何类型</span></span><br><span class="line">builder.append(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">builder.append(<span class="string">&quot;world&quot;</span>);</span><br><span class="line">builder.append(<span class="keyword">true</span>);</span><br><span class="line">builder.append(<span class="number">100</span>);</span><br><span class="line"><span class="comment">// 在我们开发中，会遇到调用一个方法后，返回一个对象的情况。然后使用返回的对象继续调用方法。</span></span><br><span class="line">        <span class="comment">// 这种时候，我们就可以把代码现在一起，如append方法一样，代码如下</span></span><br><span class="line"><span class="comment">//链式编程</span></span><br><span class="line">builder.append(<span class="string">&quot;hello&quot;</span>).append(<span class="string">&quot;world&quot;</span>).append(<span class="keyword">true</span>).append(<span class="number">100</span>);</span><br><span class="line">System.out.println(<span class="string">&quot;builder:&quot;</span>+builder);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>备注：StringBuilder已经覆盖重写了Object当中的toString方法。</p></blockquote><h3 id="toString方法"><a href="#toString方法" class="headerlink" title="toString方法"></a>toString方法</h3><p>通过toString方法，StringBuilder对象将会转换为不可变的String对象。如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo16StringBuilder</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 链式创建</span></span><br><span class="line">        StringBuilder sb = <span class="keyword">new</span> StringBuilder(<span class="string">&quot;Hello&quot;</span>).append(<span class="string">&quot;World&quot;</span>).append(<span class="string">&quot;Java&quot;</span>);</span><br><span class="line">        <span class="comment">// 调用方法</span></span><br><span class="line">        String str = sb.toString();</span><br><span class="line">        System.out.println(str); <span class="comment">// HelloWorldJava</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="第五章-包装类"><a href="#第五章-包装类" class="headerlink" title="第五章 包装类"></a>第五章 包装类</h1><h2 id="5-1-概述"><a href="#5-1-概述" class="headerlink" title="5.1 概述"></a>5.1 概述</h2><p>Java提供了两个类型系统，基本类型与引用类型，使用基本类型在于效率，然而很多情况，会创建对象使用，因为对象可以做更多的功能，如果想要我们的基本类型像对象一样操作，就可以使用基本类型对应的包装类，如下：</p><table><thead><tr><th>基本类型</th><th>对应的包装类（位于java.lang包中）</th></tr></thead><tbody><tr><td>byte</td><td>Byte</td></tr><tr><td>short</td><td>Short</td></tr><tr><td>int</td><td><strong>Integer</strong></td></tr><tr><td>long</td><td>Long</td></tr><tr><td>float</td><td>Float</td></tr><tr><td>double</td><td>Double</td></tr><tr><td>char</td><td><strong>Character</strong></td></tr><tr><td>boolean</td><td>Boolean</td></tr></tbody></table><h2 id="5-2-装箱与拆箱"><a href="#5-2-装箱与拆箱" class="headerlink" title="5.2 装箱与拆箱"></a>5.2 装箱与拆箱</h2><p>基本类型与对应的包装类对象之间，来回转换的过程称为”装箱“与”拆箱“：</p><ul><li><p><strong>装箱</strong>：从基本类型转换为对应的包装类对象。</p></li><li><p><strong>拆箱</strong>：从包装类对象转换为对应的基本类型。</p></li></ul><p>用Integer与 int为例：（看懂代码即可）</p><p>基本数值—-&gt;包装对象</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Integer i = <span class="keyword">new</span> Integer(<span class="number">4</span>);<span class="comment">//使用构造函数函数</span></span><br><span class="line">Integer iii = Integer.valueOf(<span class="number">4</span>);<span class="comment">//使用包装类中的valueOf方法</span></span><br></pre></td></tr></table></figure><p>包装对象—-&gt;基本数值</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> num = i.intValue();</span><br></pre></td></tr></table></figure><h2 id="5-3自动装箱与自动拆箱"><a href="#5-3自动装箱与自动拆箱" class="headerlink" title="5.3自动装箱与自动拆箱"></a>5.3自动装箱与自动拆箱</h2><p>由于我们经常要做基本类型与包装类之间的转换，从Java 5（JDK 1.5）开始，基本类型与包装类的装箱、拆箱动作可以自动完成。例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Integer i = <span class="number">4</span>;<span class="comment">//自动装箱。相当于Integer i = Integer.valueOf(4);</span></span><br><span class="line">i = i + <span class="number">5</span>;<span class="comment">//等号右边：将i对象转成基本数值(自动拆箱) i.intValue() + 5;</span></span><br><span class="line"><span class="comment">//加法运算完成后，再次装箱，把基本数值转成对象。</span></span><br></pre></td></tr></table></figure><h2 id="5-3-基本类型与字符串之间的转换"><a href="#5-3-基本类型与字符串之间的转换" class="headerlink" title="5.3 基本类型与字符串之间的转换"></a>5.3 基本类型与字符串之间的转换</h2><h3 id="基本类型转换为String"><a href="#基本类型转换为String" class="headerlink" title="基本类型转换为String"></a>基本类型转换为String</h3><p>   基本类型转换String总共有三种方式，查看课后资料可以得知，这里只讲最简单的一种方式： </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">基本类型直接与””相连接即可；如：34+&quot;&quot;</span><br></pre></td></tr></table></figure><p>String转换成对应的基本类型 </p><p>除了Character类之外，其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型：</p><ul><li><code>public static byte parseByte(String s)</code>：将字符串参数转换为对应的byte基本类型。</li><li><code>public static short parseShort(String s)</code>：将字符串参数转换为对应的short基本类型。</li><li><code>public static int parseInt(String s)</code>：将字符串参数转换为对应的int基本类型。</li><li><code>public static long parseLong(String s)</code>：将字符串参数转换为对应的long基本类型。</li><li><code>public static float parseFloat(String s)</code>：将字符串参数转换为对应的float基本类型。</li><li><code>public static double parseDouble(String s)</code>：将字符串参数转换为对应的double基本类型。</li><li><code>public static boolean parseBoolean(String s)</code>：将字符串参数转换为对应的boolean基本类型。</li></ul><p>代码使用（仅以Integer类的静态方法parseXxx为例）如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo18WrapperParse</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> num = Integer.parseInt(<span class="string">&quot;100&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注意:如果字符串参数的内容无法正确转换为对应的基本类型，则会抛出<code>java.lang.NumberFormatException</code>异常。</p></blockquote>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记06-Map集合</title>
      <link href="java/javase/note/note06/"/>
      <url>java/javase/note/note06/</url>
      
        <content type="html"><![CDATA[<h1 id="Map集合"><a href="#Map集合" class="headerlink" title="Map集合"></a>Map集合</h1><h3 id="学习目标"><a href="#学习目标" class="headerlink" title="学习目标"></a>学习目标</h3><ul><li>能够说出Map集合特点</li><li>使用Map集合添加方法保存数据</li><li>使用”键找值”的方式遍历Map集合</li><li>使用”键值对”的方式遍历Map集合</li><li>能够使用HashMap存储自定义键值对的数据</li><li>能够使用HashMap编写斗地主洗牌发牌案例</li></ul><h3 id="Map集合概述"><a href="#Map集合概述" class="headerlink" title="Map集合概述"></a>Map集合概述</h3><p>啥也不用说,Map集合就相当于python中的字典</p><p>Java提供了专门的集合类用来存放这种对象关系的对象，即 java.util.Map 接口。</p><p>说白了就是键值对儿的形式存的数据</p><h3 id="Map接口中的常用方法"><a href="#Map接口中的常用方法" class="headerlink" title="Map接口中的常用方法"></a>Map接口中的常用方法</h3><p>Map接口中定义了很多方法，常用的如下：</p><ul><li>public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中。</li><li>public V remove(Object key) : 把指定的键 所对应的键值对元素 在Map集合中删除，返回被删除元素的<br>值。</li><li>public V get(Object key) 根据指定的键，在Map集合中获取对应的值。</li><li>public Set<K> keySet() : 获取Map集合中所有的键，存储到Set集合中。</li><li>public Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)。</li></ul><h3 id="Map接口的方法演示"><a href="#Map接口的方法演示" class="headerlink" title="Map接口的方法演示"></a>Map接口的方法演示</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"><span class="comment">//创建 map对象</span></span><br><span class="line">        HashMap&lt;String, String&gt; map = <span class="keyword">new</span> HashMap&lt;String, String&gt;();</span><br><span class="line"><span class="comment">//添加元素到集合</span></span><br><span class="line">        map.put(<span class="string">&quot;黄晓明&quot;</span>, <span class="string">&quot;杨颖&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;黄晓明&quot;</span>, <span class="string">&quot;杨颖2&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;文章&quot;</span>, <span class="string">&quot;马伊琍&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;邓超&quot;</span>, <span class="string">&quot;孙俪&quot;</span>);</span><br><span class="line">        System.out.println(map);</span><br><span class="line"><span class="comment">//String remove(String key)</span></span><br><span class="line">        System.out.println(map.remove(<span class="string">&quot;邓超&quot;</span>));</span><br><span class="line">        System.out.println(map);</span><br><span class="line"><span class="comment">// 想要查看 黄晓明的媳妇 是谁</span></span><br><span class="line">        System.out.println(map.get(<span class="string">&quot;黄晓明&quot;</span>));</span><br><span class="line">        System.out.println(map.get(<span class="string">&quot;邓超&quot;</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果:</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;邓超=孙俪, 文章=马伊琍, 黄晓明=杨颖&#125;</span><br><span class="line">孙俪</span><br><span class="line">&#123;文章=马伊琍, 黄晓明=杨颖&#125;</span><br><span class="line">杨颖</span><br><span class="line">null</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>如何直接在网页中显示PDF文件</title>
      <link href="front/html-pdf/"/>
      <url>front/html-pdf/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「北方的刀郎」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。</p><p>原文链接：<a href="https://blog.csdn.net/forest_fire/article/details/50944069">https://blog.csdn.net/forest_fire/article/details/50944069</a></p><p>博客分类： web开发 </p><h3 id="1、"><a href="#1、" class="headerlink" title="1、"></a>1、</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">embed</span> <span class="attr">width</span>=<span class="string">&quot;800&quot;</span> <span class="attr">height</span>=<span class="string">&quot;600&quot;</span> <span class="attr">src</span>=<span class="string">&quot;test_pdf.pdf&quot;</span>&gt;</span> <span class="tag">&lt;/<span class="name">embed</span>&gt;</span> </span><br></pre></td></tr></table></figure><p>通过的浏览器：360、Firefox、IE、Chrome </p><h3 id="2、"><a href="#2、" class="headerlink" title="2、"></a>2、</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">object</span> <span class="attr">classid</span>=<span class="string">&quot;clsid:CA8A9780-280D-11CF-A24D-444553540000&quot;</span> <span class="attr">width</span>=<span class="string">&quot;800&quot;</span> <span class="attr">height</span>=<span class="string">&quot;600&quot;</span> <span class="attr">border</span>=<span class="string">&quot;0&quot;</span>&gt;</span> </span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">param</span> <span class="attr">name</span>=<span class="string">&quot;SRC&quot;</span> <span class="attr">value</span>=<span class="string">&quot;test_pdf.pdf&quot;</span>&gt;</span> </span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">object</span>&gt;</span> </span><br></pre></td></tr></table></figure><h3 id="下面这个完整点："><a href="#下面这个完整点：" class="headerlink" title="下面这个完整点："></a>下面这个完整点：</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">object</span> <span class="attr">classid</span>=<span class="string">&quot;clsid:CA8A9780-280D-11CF-A24D-444553540000&quot;</span> <span class="attr">width</span>=<span class="string">&quot;100%&quot;</span> <span class="attr">height</span>=<span class="string">&quot;100%&quot;</span> <span class="attr">border</span>=<span class="string">&quot;0&quot;</span>&gt;</span><span class="comment">&lt;!--IE--&gt;</span> </span><br><span class="line">      <span class="tag">&lt;<span class="name">param</span> <span class="attr">name</span>=<span class="string">&quot;_Version&quot;</span> <span class="attr">value</span>=<span class="string">&quot;65539&quot;</span>&gt;</span> </span><br><span class="line">      <span class="tag">&lt;<span class="name">param</span> <span class="attr">name</span>=<span class="string">&quot;_ExtentX&quot;</span> <span class="attr">value</span>=<span class="string">&quot;20108&quot;</span>&gt;</span> </span><br><span class="line">      <span class="tag">&lt;<span class="name">param</span> <span class="attr">name</span>=<span class="string">&quot;_ExtentY&quot;</span> <span class="attr">value</span>=<span class="string">&quot;10866&quot;</span>&gt;</span> </span><br><span class="line">      <span class="tag">&lt;<span class="name">param</span> <span class="attr">name</span>=<span class="string">&quot;_StockProps&quot;</span> <span class="attr">value</span>=<span class="string">&quot;0&quot;</span>&gt;</span> </span><br><span class="line">      <span class="tag">&lt;<span class="name">param</span> <span class="attr">name</span>=<span class="string">&quot;SRC&quot;</span> <span class="attr">value</span>=<span class="string">&quot;testing_pdf.pdf&quot;</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">embed</span> <span class="attr">src</span>=<span class="string">&quot;testing_pdf.pdf&quot;</span> <span class="attr">width</span>=<span class="string">&quot;100%&quot;</span> <span class="attr">height</span>=<span class="string">&quot;800&quot;</span> <span class="attr">href</span>=<span class="string">&quot;testing_pdf.pdf&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">embed</span>&gt;</span><span class="comment">&lt;!--FF--&gt;</span> </span><br><span class="line"><span class="tag">&lt;/<span class="name">object</span>&gt;</span> </span><br></pre></td></tr></table></figure><p>通过的浏览器：360、IE </p><p>未通过的浏览器：Firefox、Chrome </p><p>3、</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">iframe</span> <span class="attr">src</span>=<span class="string">&quot;test_pdf.pdf&quot;</span> <span class="attr">width</span>=<span class="string">&quot;800&quot;</span> <span class="attr">height</span>=<span class="string">&quot;600&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">iframe</span>&gt;</span> </span><br></pre></td></tr></table></figure><p>通过的浏览器：360、Firefox、IE、Chrome </p><p>4、用浏览器直接访问<a href="http://127.0.0.1/test_pdf.pdf">http://127.0.0.1/test_pdf.pdf</a> (其实这个不算是在网页内吧) </p><p>通过的浏览器：360、Firefox、IE、Chrome </p><p>以上四种方式均在WinXP下。（之前有碰到过上传的功能在Win7下失效的情况，故在此说明一下OS）</p><hr><p>今天有一需求，要在网页中显示pdf，于是立马开始搜索解决方案，无意中发现一个非常好的解决方法，详见<a href="http://blogs.adobe.com/pdfdevjunkie/web_designers_guide%E3%80%82">http://blogs.adobe.com/pdfdevjunkie/web_designers_guide。</a></p><p>其实就光看这个网站也足够了，<a href="http://www.pdfobject.com/%E3%80%82">http://www.pdfobject.com/。</a></p><p>记录一下主要代码：</p><p>pdfobject.js 下载:<a href="http://pan.baidu.com/s/1kTJTiqr">http://pan.baidu.com/s/1kTJTiqr</a>     <a href="http://pan.baidu.com/s/1kTJTiqr">http://pan.baidu.com/s/1kTJTiqr</a></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;scripts/pdfobject/pdfobject.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span> </span><br><span class="line"><span class="javascript"><span class="built_in">window</span>.onload = <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> success = <span class="keyword">new</span> PDFObject(&#123; <span class="attr">url</span>: <span class="string">&quot;pdf/CGVET22-08-2011V2P.pdf&quot;</span> ,<span class="attr">pdfOpenParams</span>: &#123; <span class="attr">scrollbars</span>: <span class="string">&#x27;0&#x27;</span>, <span class="attr">toolbar</span>: <span class="string">&#x27;0&#x27;</span>, <span class="attr">statusbar</span>: <span class="string">&#x27;0&#x27;</span>&#125;&#125;).embed(<span class="string">&quot;pdf1&quot;</span>);</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span> </span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;pdf1&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:700px; height:600px;&quot;</span>&gt;</span>It appears you don&#x27;t have Adobe Reader or PDF support in this web browser. <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;~/pdf/CGVET22-08-2011V2P.pdf&quot;</span>&gt;</span>Click here to download the PDF<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记04-核心类库</title>
      <link href="java/javase/note/note04/"/>
      <url>java/javase/note/note04/</url>
      
        <content type="html"><![CDATA[<h3 id="Object类"><a href="#Object类" class="headerlink" title="Object类"></a>Object类</h3><h4 id="1-1-常用的包"><a href="#1-1-常用的包" class="headerlink" title="1.1 常用的包"></a>1.1 常用的包</h4><pre><code>java.lang包  -该包是Java语言中的核心包,该包中的内容由Java虚拟机自动导入如:String类,System类等java.util包- 该包是Java语言中的工具包,里面包含了大量的工具类和集合类等java.io包 是输入输出包,包括读写各种设备java.net包 是网络编程包,包括各种网络编程java.sql包 是操作数据库的所有类和接口</code></pre><p>Java程序员在编程时,可以使用大量的类库,因此,java编程需要记的很多,对编程能力的本身要求不是特别的高.</p><h3 id="第三个阶段"><a href="#第三个阶段" class="headerlink" title="第三个阶段"></a>第三个阶段</h3><p>从这个阶段开始,我们不需要自己来写一些类了</p><p>而是要学习系统给我们写好的一些类了,这部分最好需要随时来查询API文档</p><h4 id="Object类-1"><a href="#Object类-1" class="headerlink" title="Object类"></a>Object类</h4><ol><li>基本概念<br> java.lang.Object类是所有类层次结构的根类,任何类都是该类的直接或间接子类.<br> (也验证了那就话,<code>万物皆对象</code>)</li><li>常用的方法<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">Object() - 使用无参方式构造对象</span><br><span class="line"><span class="function"><span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object obj)</span> - 用于判断调用对象是否与参数对象相等</span></span><br><span class="line"><span class="function">    - 该方法默认比较两个对象的地址,与</span>== 运算符结果相同</span><br><span class="line">    - 为了使得该方法比较两个对象的内容,则需要重写该方法</span><br><span class="line">    - 若该方法重写后,则应该重写hashCode()方法来维护hashCode方法的常规协定</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">hashCode</span><span class="params">()</span> - 用于获取调用对象的哈希码值<span class="params">(内存地址的编号)</span></span></span><br><span class="line"><span class="function">    - 若调用equals方法的结果相等,则各自调用hashCode方法的结果相同</span></span><br><span class="line"><span class="function">    - 若调用equals方法的结果不相等,则各自调用hashCode方法的结果不相同</span></span><br><span class="line"><span class="function">    - 为了维护上述的常规协定与equals方法结果保持一致,就需要重写该方法</span></span><br><span class="line"><span class="function">String <span class="title">toString</span><span class="params">()</span>方法 - 用于获取对象的字符串形式</span></span><br><span class="line"><span class="function">    - 该方法默认返回的字符串为:包名.类名@哈希码值的十六进制形式</span></span><br><span class="line"><span class="function">    - 为了返回更有意义的数据内容,则需要重写该方法</span></span><br><span class="line"><span class="function">    - 当字符串内容与引用进行连接时,自动调用<span class="title">toString</span><span class="params">()</span>方法</span></span><br><span class="line"><span class="function">    - 当使用<span class="title">print</span><span class="params">()</span>或<span class="title">println</span><span class="params">()</span>方法打印引用时,或者用+连接时候,调用该方法</span></span><br></pre></td></tr></table></figure></li></ol><h3 id="equals方法"><a href="#equals方法" class="headerlink" title="equals方法"></a>equals方法</h3><p>equals方法用于判断对象是否”相等”</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">equals(Object obj)</span><br><span class="line"><span class="comment">// 这么定义的好处是,所有的类都能够作为的参数传递进来</span></span><br><span class="line"><span class="comment">// 大不了就形成多态呗!</span></span><br></pre></td></tr></table></figure><p>多态无处不在</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">boolean equals(Object obj)</span><br></pre></td></tr></table></figure><p>要想调用这个方法,这个引用必须是非空的引用,不然会引起空指针异常</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">自反性: 自个儿跟自个儿比都相等,废话  </span><br><span class="line">对称性: y.equals(x)相等 -&gt; x.equals(y)  </span><br><span class="line">传递性: x与y等,y与z等,那么x与z等  </span><br><span class="line">一致性: x与y等,x还是与y等  </span><br><span class="line">对于空: x(非空).equals(<span class="keyword">null</span>)结果为<span class="keyword">false</span>  </span><br></pre></td></tr></table></figure><p>说白了equals就是比较引用类型的地址信息<br>与 == 运算符等价</p><h3 id="包装类和数学处理类"><a href="#包装类和数学处理类" class="headerlink" title="包装类和数学处理类"></a>包装类和数学处理类</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Person p = <span class="keyword">new</span> Person();</span><br><span class="line"><span class="comment">// 声明Person类型的引用,指向Person类型的对象</span></span><br><span class="line"><span class="keyword">int</span> num = <span class="number">10</span>;</span><br><span class="line"><span class="comment">// 声明一个int类型的变量num初始值为10</span></span><br><span class="line"><span class="comment">// Java语言是一门纯面向对象的编程语言</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 对于八种不是对象类型的变量,我们就要想办法把他们包装成面向对象的 --&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">包装类概念</span><br><span class="line">    由于Java语言是一门纯面向对象的编程语言,而<span class="number">8</span>种基本数据类型声明的变量并不是对象,为了满足Java语言的特性就需要对这些变量进行对象化处理,而实现该功能的相关类就叫做包装类</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">包装类的分类</span><br><span class="line">    <span class="keyword">int</span> -&gt; java.lang.Integer类</span><br><span class="line">    <span class="keyword">char</span> -&gt; java.lang.Character类</span><br><span class="line">    其他类型对应的包装类就是首字母变为大写的</span><br></pre></td></tr></table></figure><p>Integer类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">基本概念:</span><br><span class="line">    java.lang.Integer类是<span class="keyword">int</span>类型的包装类,里面包含了一个<span class="keyword">int</span>类型的成员变量.</span><br><span class="line">    该类有<span class="keyword">final</span>关键字修饰表示不能被继承</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">常用方法</span><br><span class="line">    Integer(int value) - 根据参数指定的整数构造对象</span><br><span class="line">    Integer(String s) - 根据参数知指定的字符串构造对象</span><br><span class="line">    该类重写了equals(), hashCode() toString()方法</span><br></pre></td></tr></table></figure><h3 id="包装类"><a href="#包装类" class="headerlink" title="包装类"></a>包装类</h3><p>基本数据类型,使用起来非常方便,但是没有对应的方法来操作这些数据类型的数据,可以使用一个类,把基本数据类型装起来,在类中定义一些方法,这个类叫做包装类,我们可以使用类中的方法来操作这些基本数据类型的数据</p><h3 id="装箱与拆箱"><a href="#装箱与拆箱" class="headerlink" title="装箱与拆箱"></a>装箱与拆箱</h3><ul><li>装箱:</li><li>把基本数据类型的数据,包装到包装类中(基本数据类型的数据-&gt;包装类)</li><li>构造方法:</li><li> Integer(int value)</li><li> 静态方法:</li><li></li><li>拆箱:</li><li> 在包装类中取出基本类型数据(包装类-&gt;基本类型数据)</li><li> 成员方法:int intValue() 以int 类型返回该Integer的值</li><li></li></ul><h3 id="基本类型与字符串类型之间的相互转换"><a href="#基本类型与字符串类型之间的相互转换" class="headerlink" title="基本类型与字符串类型之间的相互转换"></a>基本类型与字符串类型之间的相互转换</h3><ul><li>基本类型 -&gt; 字符串(String)</li><li><ol><li>基本类型的值+”” 最简单的方法(工作中常用)</li></ol></li><li><ol start="2"><li>包装类的静态方法toString(参数),不是Object类的toString()重载</li></ol></li><li><ol start="3"><li>String类的静态方法valueOf(参数)</li></ol></li><li>static String valueOf(int i) 返回int 参数的字符串表示形式</li><li>字符串(String) -&gt; 基本类型</li><li> 使用包装类的静态方法paresXXX(“字符串”);</li><li><pre><code> Integer类:static int parseInt(String s)</code></pre></li><li><pre><code> Double类: static double parseDouble(String s)</code></pre></li></ul><h4 id="String转换成对应的基本数据类型"><a href="#String转换成对应的基本数据类型" class="headerlink" title="String转换成对应的基本数据类型"></a>String转换成对应的基本数据类型</h4><p>除了Character类之外,其他所有包装类都具有parseXXX静态方法可以将字符串参数转换为对应的基本类型:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> i = Integer.parseInt(s3);</span><br><span class="line"><span class="keyword">float</span> ff = Float.parseFloat(s);</span><br><span class="line"><span class="keyword">long</span> l = Long.parseLong(s);</span><br><span class="line">...</span><br><span class="line">```  </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">### 学习集合的目标:</span><br><span class="line"><span class="number">1.</span> 会使用集合存储数据</span><br><span class="line"><span class="number">2.</span> 会遍历集合,把数据取出来</span><br><span class="line"><span class="number">3.</span> 掌握每种集合</span><br><span class="line"></span><br><span class="line">### 集合框架的学习方式:</span><br><span class="line"><span class="number">1.</span> 学习底层:学习顶层接口/抽象类中共性的方法,所有的子类都可以使用</span><br><span class="line"></span><br><span class="line"><span class="number">2.</span> 使用底层:底层不是接口就是抽象类,无法创建对象使用,需要使用底层的子类创建对象使用</span><br><span class="line"></span><br><span class="line">### 容器类数据包含结构</span><br><span class="line">继承:子类共性抽取,形成父类(接口)</span><br><span class="line">```java</span><br><span class="line">Collection接口</span><br><span class="line">    List接口</span><br><span class="line">        Vector集合</span><br><span class="line">        ArrayList集合</span><br><span class="line">        LinkedList集合</span><br><span class="line">    Set接口</span><br><span class="line">        TreeSet集合</span><br><span class="line">        HashSet集合(无序)</span><br><span class="line">            LinkedHashSet集合</span><br></pre></td></tr></table></figure><p>无序的集合(存储和取出元素的顺序有可能不一致)</p><p>Collection接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">定义的是所有单列集合中共性的方法</span><br><span class="line">所有的单列集合都可以使用共性的方法</span><br><span class="line">没有带索引的方法</span><br></pre></td></tr></table></figure><p>List接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 有序集合(存储和取出元素顺序相同)</span><br><span class="line"><span class="number">2.</span> 允许存储重复的元素</span><br><span class="line"><span class="number">3.</span> 有索引,可以使用普通的<span class="keyword">for</span>循环遍历</span><br></pre></td></tr></table></figure><p>Set接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 不允许存储重复元素</span><br><span class="line"><span class="number">2.</span> 没有索引(不能使用普遍<span class="keyword">for</span>循环遍历)</span><br></pre></td></tr></table></figure><h3 id="Collection接口"><a href="#Collection接口" class="headerlink" title="Collection接口"></a>Collection接口</h3><ul><li>java.util.Collection</li><li>所有单列集合的最顶层的接口,里面定义了所有单列集合共性的方法</li><li>任意的单列集合都可以使用Collection接口中的方法</li><li>共性的方法</li><li>public boolean add(E e): 把给定的对象添加到当前集合中</li><li>public void clear():清空集合中所有的元素</li><li>public boolean remove(E e):把给定的对象在当前集合中删除</li><li>public boolean contains(E e):判断当前集合中是否包含给定的对象</li><li>public boolean isEmpty(): 判断当前集合是否为空.</li><li>public int size(): 返回集合中元素的个数.</li><li>public Object[] toArray(): 把集合中的元素,存储到数组中.</li></ul><h3 id="Iterator迭代器"><a href="#Iterator迭代器" class="headerlink" title="Iterator迭代器"></a>Iterator迭代器</h3><p>在程序开发中,经常需要遍历集合中的所有元素.针对这种需求,JDK专门提供了一个接口<code>java.util.Iterator</code>.<code>Iterator</code>接口也是Java集合中的一员,但它与<code>Collection</code>,<code>Map</code>接口有所不同,<code>Collection</code>接口与Map接口主要用于存贮元素,而<code>Iterator</code>主要用于迭代访问(即遍历)<code>Collection</code>中的元素,因此<code>Iterator</code>对象也被称为迭代器.</p><p>想要遍历<code>Collection</code>集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方法:</p><ul><li><code>public Iterator iterator()</code>:获取集合对应的迭代器,用来遍历集合中的元素的.<br>下面介绍一下迭代的概念:</li><li>迭代:即<code>Collection</code>集合元素的通用获取方式.在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来.</li></ul><p>一直把集合中的所有元素全部取出.这种取出方式专业术语称为<code>迭代</code></p><p><code>Iterator</code>接口的常用方法如下:</p><ul><li><code>public E next()</code>:返回迭代的下一个元素.</li><li><code>public boolean hasNext()</code>:如果仍有元素可以迭代,则返回true</li></ul><ul><li>java.util.Iterator 接口:迭代器(对集合进行遍历)</li><li>有两个常用的方法</li><li>boolean hasNext() 如果仍有元素可以迭代,则返回true</li><li>E next() 返回迭代的下一个元素</li><li>取出集合中的下一个元素</li><li>Iterator 迭代器,是一个接口,我们无法直接使用,需要使用ITerator接口的实现类对象,获取实现类的方式比较特殊</li><li>Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象</li><li>Iterator<E> iterator()</li><li>返回在此 collection 的元素进行迭代的迭代器</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jetbrains IDE 设置和 license</title>
      <link href="ide/jetbrains/jetbrains-license-settings/"/>
      <url>ide/jetbrains/jetbrains-license-settings/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>jetbrains系列的IDE被认为是业内最强大的集成开发环境</p><p>小编收集了一些方便的个性化设置</p><p>如有需要可以自行下载:</p><p><a href="https://github.com/victorfengming/jetbrains_settings">victorfengming/jetbrains_settings</a></p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/jetbrains_settings.png" alt="jetbrains_settings"></p><p>感觉有用的同学可以帮小编<code>Star</code>一下</p><p>您的支持就是我的动力</p><p>需要license的同学可以来:<a href="http://idea.medeming.com/jets/">这里</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>sublime text 配置java开发环境</title>
      <link href="ide/sublime/sublime-java/"/>
      <url>ide/sublime/sublime-java/</url>
      
        <content type="html"><![CDATA[<ul><li>把SublimeText当作一个轻量级的编译工具来用还是不错的，可是当我下载好并且写了一个HelloWord的Java程序之后，它居然只编译不运行！那么我们就来解决这个问题</li><li>注意：本教程针对的是Windows平台，Mac OS我已经试过了，并不行。</li></ul><h2 id="变化"><a name="t1"></a>变化</h2><ul><li>原本网上是有一些关于sublime text 2的教程的，可是Sublime Text 3 和2 有些区别，主要是原来的一些配置文件都被压缩成一个文件了。下面我们就来看看如何让Java程序在Sublime Text中编译和运行。</li></ul><h2 id="准备"><a name="t2"></a>准备</h2><ul><li>如果你已经配置好了JDK并且安装好了Sublime Text 3 ，那么就可以继续看下去了，否则，你应该先去配置环境和安装软件。</li></ul><h2 id="教程"><a name="t3"></a>教程</h2><ol><li>首先找到Sublime Text 3 安装目录下的<code>Java.sublime-package</code>文件。我的这个文件是在<code>C:\Program Files\Sublime Text 3\Packages</code></li><li>使用WinRAR或者其他解压软件打开上一步中说的文件</li><li>找到<code>JavaC.sublime-build</code>文件并且使用Sublime Text 3 打开，修改内容为下文给出的内容</li><li>然后保存，WinRAR会提示是否保存修改的文件到压缩文件，当然选是</li></ol><h2 id="javacsublime-build"><a name="t4"></a>JavaC.sublime-build</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;cmd&quot;</span>: [<span class="string">&quot;javac&quot;</span>, <span class="string">&quot;$file_name&quot;</span>, <span class="string">&quot;&amp;&amp;&quot;</span>, <span class="string">&quot;java&quot;</span>, <span class="string">&quot;$file_base_name&quot;</span>], </span><br><span class="line">    <span class="string">&quot;working_dir&quot;</span>: <span class="string">&quot;$&#123;project_path:$&#123;folder&#125;&#125;&quot;</span>, </span><br><span class="line">    <span class="string">&quot;selector&quot;</span>: <span class="string">&quot;source.java&quot;</span>, </span><br><span class="line">    <span class="string">&quot;shell&quot;</span>: true, </span><br><span class="line">    <span class="string">&quot;encoding&quot;</span>:<span class="string">&quot;utf-8&quot;</span> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="然后然我们来看看结果如何"><a name="t5"></a>然后然我们来看看结果如何</h2><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/sublime_java.png" alt="sublime_java" title=""> <br>It Works！！！</p>                                  ]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> sublime </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>sublime text 背景半透明设置</title>
      <link href="ide/sublime/sublime-transparent/"/>
      <url>ide/sublime/sublime-transparent/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「tonasy」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。</p><p>原文链接：<a href="https://blog.csdn.net/esting_tang/article/details/52876226">https://blog.csdn.net/esting_tang/article/details/52876226</a></p><div class="htmledit_views" id="content_views">                                            <p>目前知道的两种方法设置（个人推荐使用方法1）：</p><h3>方法1：</h3><p>打开sublime text3，Ctrl+shift+P，install package，transparency，依次输入以上命令进行安装，安装完成后可以在菜单View-Window's transparency下进行调节。</p><p>觉得好用的朋友可以在<a href="https://github.com/vhanla/SublimeTextTrans" rel="nofollow" data-token="31baa5c269a03297b6d8ab40099432e7">这里</a>给原作者点个star。</p><h3>方法2：使用插件，如下：</h3><p>第一步：软件下载地址：http://pan.baidu.com/s/1jHYzKl4</p><p>第二步：解压安装</p><p>第三步：设置打开此半透明窗口的快捷键</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20161020200214175"></p><p>第四步：设置透明度（这里我设置的最低）</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20161020200253335"></p><p>OK，大功告成了~看看效果吧：</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20161020200357192"></p><p>&nbsp;</p>                                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> sublime </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记03-Constructor &amp; Override</title>
      <link href="java/javase/note/note03/"/>
      <url>java/javase/note/note03/</url>
      
        <content type="html"><![CDATA[<h3 id="构造方法基本概念"><a href="#构造方法基本概念" class="headerlink" title="构造方法基本概念"></a>构造方法基本概念</h3><p>构造方法是类中的一种特殊方法</p><p>它是在类创建对象(实例化)的时候自动调用的方法</p><p>这个和python中的<code>__init__</code>初始化魔术方法类似</p><p>可以在创建对象的时候进行参数的传递</p><h3 id="默认送您的构造"><a href="#默认送您的构造" class="headerlink" title="默认送您的构造"></a>默认送您的构造</h3><p>一个类编译过后都需要有一个构造方法.如果程序中没有写的话</p><p>编译器在编译时就会帮你加上一个无参数的空的构造方法(称之为”默认的构造方法”)</p><p>那要是你定义了构造方法了,编译器也不欠欠的帮你加了,它也懒</p><h3 id="关于构造的建议"><a href="#关于构造的建议" class="headerlink" title="关于构造的建议"></a>关于构造的建议</h3><ul><li><p>当类中有成员变量,并且还不是常量的时候,建议提供两个版本的构造方法,一个无参数的构造,一个全属性的构造</p></li><li><p>而类中所有成员变量都是常量或者干脆就没有成员变量的时候,建议不要写构造</p></li></ul><h3 id="成员方法重载"><a href="#成员方法重载" class="headerlink" title="成员方法重载"></a>成员方法重载</h3><p>说白了就是同样名称的方法,可以有很多不同参数列表的版本,有的有参数,有的没有参数,而方法名一样</p><p>这样官方说能让类的设计变的更加优雅,我是没看出来</p><p>好像是能够一个方法处理不同的数据</p><p>这样的设计方式成为重载设计</p><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101608.png"><h3 id="this关键字"><a href="#this关键字" class="headerlink" title="this关键字"></a>this关键字</h3><p><code>this</code>就是代表对象本身(调用该方法的对象)<br>就像<code>JavaScript</code>中的<code>this</code><br>就像<code>python</code>中的<code>self</code>  </p><h3 id="OOP三大特性之封装"><a href="#OOP三大特性之封装" class="headerlink" title="OOP三大特性之封装"></a>OOP三大特性之封装</h3><p>封装的面向对象的三大特性之一,</p><p>如果代码不做限制,则很多属性值是无效的</p><p>封装就是保证属性值有效的技术</p><h3 id="封装的步骤"><a href="#封装的步骤" class="headerlink" title="封装的步骤"></a>封装的步骤</h3><ol><li><p>属性(不是常量的)必须使用private修饰,确保外部变量无法直接进行赋值操作</p></li><li><p>提供操作属性的方法,一般都是读写属性方法,get属性和set属性方法</p></li><li><p>构造方法中,也要通过调用set和get方法来操作</p></li></ol><h3 id="static关键字"><a href="#static关键字" class="headerlink" title="static关键字"></a>static关键字</h3><p>静态static关键字修饰属性或者方法</p><p>可以将对象层级从对象级升级成为类级别,在类加载的时候就可以调用准备好的属性或者方法</p><p>换句话说就是static修饰的可以直接进行调用</p><h3 id="单例设计模式"><a href="#单例设计模式" class="headerlink" title="单例设计模式"></a>单例设计模式</h3><p>设计模式是形成标准化流程的经验总结,是特定问题的固定的解决方案</p><p>单例设计思路:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. 先private构造,阻止外部去创建对象</span><br><span class="line">2. 本类提供一个对象,定义一个private static 的本类类型的属性  </span><br><span class="line">3. 对外提供get方法,将唯一的对象返回到外部  </span><br></pre></td></tr></table></figure><p>单例分为饿汉式和懒汉式两种写法</p><p>java中单例模式是一种常见的设计模式，在实际开发中比较常用<br>具体详细内容可以参考:<a href="https://victorfengming.gitee.io/blog/java-single-case/">Java设计模式之单例模式</a></p><h3 id="OOP三大特性之继承"><a href="#OOP三大特性之继承" class="headerlink" title="OOP三大特性之继承"></a>OOP三大特性之继承</h3><p>继承就是子类复用父类的代码</p><p>使用关键字extends表示类和类之间的继承关系</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Son</span> <span class="keyword">extends</span> <span class="title">Father</span></span>&#123;</span><br><span class="line">    <span class="comment">// ... </span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Java中不能多继承,可以通过接口的多实现来弥补类的多继承</p><h3 id="继承中的构造方法"><a href="#继承中的构造方法" class="headerlink" title="继承中的构造方法"></a>继承中的构造方法</h3><p>子类必须通过<code>super();</code>关键字才能调用父类中的构造方法</p><p>这样才能好好的初始化来自父类的成员变量</p><p><code>this()</code>和<code>super()</code>必须出现在构造的第一行,因此不可能同时出现</p><h3 id="方法的重写"><a href="#方法的重写" class="headerlink" title="方法的重写"></a>方法的重写</h3><ul><li>有些父类写好的方法,子类它不太喜欢</li></ul><p>子类就可以使用方法重写(覆盖)来改变他爸爸给他的方法</p><ul><li>方法重写的原则:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. 相同的方法名称,相同的参数列表,相同的返回值类型或者返回子类</span><br><span class="line">2. 访问权限不能变小,可以变大</span><br><span class="line">3. 不能抛出更大的异常</span><br></pre></td></tr></table></figure></li><li>在子类重写的方法中,可以通过<code>super</code>关键字调用父类的”原始”方法.</li><li><code>static</code> 方法重写之后还是<code>static</code>的</li></ul><h3 id="访问控制修饰符的对比"><a href="#访问控制修饰符的对比" class="headerlink" title="访问控制修饰符的对比"></a>访问控制修饰符的对比</h3><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101609.png"><h3 id="OOP三大特性之多态"><a href="#OOP三大特性之多态" class="headerlink" title="OOP三大特性之多态"></a>OOP三大特性之多态</h3><p>一母生九子,九子各不同</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Person p = <span class="keyword">new</span> Student();</span><br></pre></td></tr></table></figure><ol><li>只能使用母类中定义的属性和方法</li><li>不能直接使用子类中扩展的属性和方法</li><li>如果子类重写了方法,静态方法调父类的,非静态方法调子类的<br>原因:<br> 编译时,p被认为是Person类型;但在运行时是Student类型.在内存中其实是子类对象.</li></ol><p>总结:<br><code>左</code>父<code>右</code>子即为多态</p><h3 id="多态特点"><a href="#多态特点" class="headerlink" title="多态特点"></a>多态特点</h3><p>多态时,如果想要把扩展的属性和方法调用出来,需要做类型转换</p><p><code>父类</code>转<code>子类</code>需要做强制类型转换(向<code>下</code>转型)<br><code>子类</code>转<code>父类</code>需要做强制类型转换(向<code>上</code>转型)</p><p>对象强制类型转换是一种还原行为,必须内存中是该类型的对象才能成功</p><h3 id="instanceof运算符"><a href="#instanceof运算符" class="headerlink" title="instanceof运算符"></a>instanceof运算符</h3><p><code>instanceof</code>就是判断对象的类型,如果是该类型返回<code>true</code>,不是返回<code>false</code></p><p>语法格式:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">对象 <span class="keyword">instanceof</span> 类型</span><br><span class="line">obj <span class="keyword">instanceof</span> Object</span><br><span class="line">p <span class="keyword">instanceof</span> Person</span><br></pre></td></tr></table></figure><p>严格的来说,在进行对象的向下转型之前,都得instanceof一下才能</p><p>这个instanceof必须发生在父子之间才行哦!</p><h3 id="抽象类"><a href="#抽象类" class="headerlink" title="抽象类"></a>抽象类</h3><p>用abstract修饰的类,这个类吧就厉害了</p><p>它不能实例化,这可咋用啊</p><p>唉,对 就是用来继承的,你不能实例化你儿子行啊</p><p>抽象方法所在类必须是抽象类,而子类如果不是抽象类,一定要重写父类中的抽象方法才行(实现父类的方法体)</p>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>删除github上的commit历史记录</title>
      <link href="git/git-clear/"/>
      <url>git/git-clear/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>今天小编发现了git克隆下来的远程库特别大:</p><p>经过查询之后发现是每次推送之后都会留下记录缓存，这样很多没用的记录就会占用多余的空间，别人克隆的时候也会多耗费时间，今天我查到了一个清除无用记录的方法。</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"># 克隆你的远程仓库</span><br><span class="line">git clone git@github.com:victorfengming/victorfengming.github.io.git</span><br><span class="line"></span><br><span class="line"># 进入你的本地库</span><br><span class="line"><span class="built_in">cd</span> victorfengming.github.io</span><br><span class="line"></span><br><span class="line"># 新建并切换到一个分支</span><br><span class="line">git checkout –orphan latest_branch</span><br><span class="line"></span><br><span class="line"># 选中全部文件</span><br><span class="line">git add -A</span><br><span class="line"></span><br><span class="line"># 提交</span><br><span class="line">git commit -am “Reinitialize”</span><br><span class="line"></span><br><span class="line"># 删除原分支</span><br><span class="line">git branch -D master</span><br><span class="line"></span><br><span class="line"># 将本分支改为原分支名</span><br><span class="line">git branch -m master</span><br><span class="line"></span><br><span class="line"># 推送到远程分支</span><br><span class="line">git push -f origin master</span><br></pre></td></tr></table></figure><p>现在你再去GitHub上去看提交分支的记录，会发现只有一次提交了</p><p>可以删除本地库重新将远程库克隆下来，这次就没有那些多余的提交记录了！</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Git仓库.git文件夹目录介绍</title>
      <link href="git/git-config-dir/"/>
      <url>git/git-config-dir/</url>
      
        <content type="html"><![CDATA[<div id="content_views" class="markdown_views prism-github-gist">                    <!-- flowchart 箭头图标 勿删 -->                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                    </svg>                                            <h2><a name="t0"></a><a id="_0"></a>说明</h2><blockquote><h3><a name="t1"></a><a id="git__1"></a>以下皆为.git/ 目录下的文件</h3></blockquote><h3><a name="t2"></a><a id="1__ORIG_HEAD_2"></a>1  ORIG_HEAD</h3><blockquote><h4><a id="__3"></a>远程仓库 当前引用</h4></blockquote><h4><a id="git__5"></a>在git本地仓库根目录 运行:</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cat .git/ORIG_HEAD<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h4><a id="_10"></a>显示</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">88e6fb86f5317bdfd2e8a78899334e9f0ba16987<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><h4><a id="_16"></a>如图：</h4><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/2018100411103066?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nvbmd5dWVxdWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="在这里插入图片描述"></p><h3><a name="t3"></a><a id="2_HEAD_18"></a>2 HEAD</h3><blockquote><h4><a id="__19"></a>本地仓库 当前引用</h4></blockquote><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"> 文件内容：refs/heads/&lt;branchName&gt;<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h4><a id="git__24"></a>在git本地仓库根目录 运行:</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cat .git/HEAD<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h4><a id="_31"></a>显示</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">ref: refs/heads/master<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><h3><a name="t4"></a><a id="3_refsheadsbranchName_38"></a>3 refs/heads/branchName</h3><blockquote><h4><a id="__40"></a>本地仓库 当前分支</h4></blockquote><h4><a id="_41"></a></h4><h4><a id="git__45"></a>在git本地仓库根目录 运行:</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cat .git/refs/heads/master<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h4><a id="_50"></a>显示</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">3396b04ee5343498d8c2f457d14d3aee36239c6f<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><blockquote><h4><a id="_commitId_57"></a>这是 当前分支最后一次commitId</h4></blockquote><h3><a name="t5"></a><a id="2__3__59"></a>2 和 3 的关系如图:</h3><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20181004111137755?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nvbmd5dWVxdWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="在这里插入图片描述"></p><h3><a name="t6"></a><a id="4_refsremotesrepertoryNameHEAD_62"></a>4 refs/remotes/repertoryName/HEAD</h3><blockquote><h4><a id="_63"></a>远程仓库当前分支</h4></blockquote><h4><a id="git__64"></a>在git本地仓库根目录 运行:</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cat .git/refs/remotes/origin/HEAD<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h4><a id="_69"></a>显示</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">ref: refs/remotes/origin/master<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><h3><a name="t7"></a><a id="5_refsremotesrepertoryNameremoteBranchName_76"></a>5 refs/remotes/repertoryName/remoteBranchName</h3><blockquote><h4><a id="commit_77"></a>远程仓库对应分支最后一次commit</h4></blockquote><h4><a id="git__78"></a>在git本地仓库根目录 运行:</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cat .git/refs/remotes/origin/master<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h4><a id="_83"></a>显示</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">581ba1436ebaa54a7f5d0f1db8cc4da0ca72127e<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><blockquote><h4><a id="commitId_89"></a>这是远程仓库当前分支最后一次commitId</h4></blockquote><h3><a name="t8"></a><a id="4__5__91"></a>4 和 5 的关系如图:</h3><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20181004111234450?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nvbmd5dWVxdWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="在这里插入图片描述"></p><h3><a name="t9"></a><a id="6_logsrefsheadsbranchName_95"></a>6 logs/refs/heads/branchName</h3><blockquote><h4><a id="_96"></a>本地仓库对应分支所有操作</h4></blockquote><h4><a id="git__98"></a>在git本地仓库根目录 运行:</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cat .git/logs/refs/heads/master <div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><h4><a id="_105"></a>显示</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">0000000000000000000000000000000000000000 88e6fb86f5317bdfd2e8a78899334e9f0ba16987 author &lt;author@youxiang.com&gt; 1537330001 +0800  clone: from https://github.com/google/guava.git<p>88e6fb86f5317bdfd2e8a78899334e9f0ba16987 581ba1436ebaa54a7f5d0f1db8cc4da0ca72127e author &lt;<a href="mailto:&#x61;&#117;&#x74;&#104;&#111;&#x72;&#x40;&#121;&#x6f;&#x75;&#x78;&#x69;&#x61;&#110;&#103;&#x2e;&#x63;&#111;&#109;">&#x61;&#117;&#x74;&#104;&#111;&#x72;&#x40;&#121;&#x6f;&#x75;&#x78;&#x69;&#x61;&#110;&#103;&#x2e;&#x63;&#111;&#109;</a>&gt; 1538568357 +0800   pull: Fast-forward</p><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre><blockquote><h4><a id="master_112"></a>本地master分支的两次操作</h4><h4><a id="1_clone__113"></a>1 clone 项目</h4></blockquote><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">commitId(0000000000000000000000000000000000000000) ——&gt; commitId(88e6fb86f5317bdfd2e8a78899334e9f0ba16987)<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><blockquote><h4><a id="2_git_pull_Fastforward_119"></a>2 git pull: Fast-forward</h4></blockquote><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">commitId(88e6fb86f5317bdfd2e8a78899334e9f0ba16987) ——&gt; commitId(581ba1436ebaa54a7f5d0f1db8cc4da0ca72127e)<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h3><a name="t10"></a><a id="7_logsrefsheadsrepertoryNamebranchName_123"></a>7 logs/refs/heads/repertoryName/branchName</h3><blockquote><h4><a id="_124"></a>远程仓库对应分支所有操作</h4></blockquote><h4><a id="git__126"></a>在git本地仓库根目录 运行:</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cat .git/logs/refs/remotes/origin/master<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h4><a id="_132"></a>显示</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">88e6fb86f5317bdfd2e8a78899334e9f0ba16987 581ba1436ebaa54a7f5d0f1db8cc4da0ca72127e songyuequan &lt;songyuequangit@163.com&gt; 1538568357 +0800  pull: fast-forward<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><blockquote><h4><a id="_137"></a>同上</h4></blockquote><h3><a name="t11"></a><a id="8_refstagstagName_139"></a>8 refs/tags/tagName</h3><blockquote><h4><a id="tagcommitID_140"></a>文件内容:tag所在的commitID</h4></blockquote><h4><a id="git__141"></a>在git本地仓库根目录 运行:</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cat  .git/refs/tags/Release1.0 <div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h4><a id="_147"></a>显示</h4><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">72014f48f489e1e43519212de1bd9f78c3755a4c<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h3><a name="t12"></a><a id="9_packedrefs_154"></a>9 packed-refs</h3><blockquote><h4><a id="clone_155"></a>clone仓库时所有的引用</h4></blockquote><h3><a name="t13"></a><a id="10_COMMIT_EDITMSG_157"></a>10 COMMIT_EDITMSG</h3><blockquote><h4><a id="_158"></a>本地最后一个提交的信息</h4></blockquote><h3><a name="t14"></a><a id="11_objects_160"></a>11 objects目录</h3><blockquote><h4><a id="_161"></a>所有文件对象</h4></blockquote><p>具体详情请看 这篇翻译文章</p><p><a href="https://blog.csdn.net/songyuequan/article/details/85862415" rel="nofollow" data-token="28a1aaa367aa941bd1bba7db61d52256">https://blog.csdn.net/songyuequan/article/details/85862415</a></p><h3><a name="t15"></a><a id="12__info_169"></a>12  info</h3><p><mark>待研究</mark></p><h3><a name="t16"></a><a id="13_index_172"></a>13 index</h3><p><a href="https://blog.csdn.net/s646575997/article/details/52143586" rel="nofollow" data-token="caeb42407afef3a7ab4480aa399bd736">Git暂存区原理</a></p><h3><a name="t17"></a><a id="14_hooks_175"></a>14 hooks</h3><p><mark>shell脚本</mark></p><pre><code>                                &lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记02-OOP</title>
      <link href="java/javase/note/note02/"/>
      <url>java/javase/note/note02/</url>
      
        <content type="html"><![CDATA[<h3 id="面向对象编程"><a href="#面向对象编程" class="headerlink" title="面向对象编程"></a>面向对象编程</h3><ul><li><p>万物皆对象</p></li><li><p>面向对象指以属性和行为的观点去分析现实生活中的事物</p></li><li><p>面向对象编程指先以面向对象的思想进行分析,然后使用面向对象的编程语言进行表达的过程</p></li><li><p>面向对象编程是软件产业化发展的需求</p></li><li><p>理解面向对象的思想精髓才行</p></li></ul><h3 id="面想对象的三大特性"><a href="#面想对象的三大特性" class="headerlink" title="面想对象的三大特性"></a>面想对象的三大特性</h3><ul><li><p>封装</p></li><li><p>继承</p></li><li><p>多态</p></li></ul><h3 id="类和对象"><a href="#类和对象" class="headerlink" title="类和对象"></a>类和对象</h3><p>类是一个抽象的定义,简单来说就是分类的类</p><p>类是用于构建对象的模板</p><p>而对对象是类的实现形式,对象的实质就是内存中的一块区域</p><p>其数据结构由创建它的类来决定</p><h3 id="类的结构"><a href="#类的结构" class="headerlink" title="类的结构"></a>类的结构</h3><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101601.png"><h3 id="对象的创建"><a href="#对象的创建" class="headerlink" title="对象的创建"></a>对象的创建</h3><p>当一个类的定义存在后,可以使用<code>new</code>运算创建该类的对象</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> 类名();</span><br></pre></td></tr></table></figure><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101602.png">### 引用的定义<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">类名作为变量类型 变量名 = <span class="keyword">new</span> 类名();</span><br></pre></td></tr></table></figure><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101603.png"><h3 id="成员变量初始化"><a href="#成员变量初始化" class="headerlink" title="成员变量初始化"></a>成员变量初始化</h3><p>对象创建后,其成员变量可以按照默认的方式初始化;</p><p>就是说你不赋值,它也有个默认值,各种数据类型的默认值如下</p><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101604.png"><h3 id="成员方法的定义"><a href="#成员方法的定义" class="headerlink" title="成员方法的定义"></a>成员方法的定义</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">方法名  </span><br><span class="line">    标识符命名规则  </span><br><span class="line">参数  </span><br><span class="line">    参数类型,多个参数  </span><br><span class="line">返回值  </span><br><span class="line">    返回值类型,多返回值  </span><br></pre></td></tr></table></figure><h3 id="JVM内存结构-方法区"><a href="#JVM内存结构-方法区" class="headerlink" title="JVM内存结构-方法区"></a>JVM内存结构-方法区</h3><p>java的程序运行是需要在内存中开辟空间的,关于java中的内存更多内容,可以参考:<a href="https://victorfengming.gitee.io/blog/java-ram/">Java中的内存浅析</a></p><p>方法区:该空间用于存放类的信息. java程序运行时,首先会通过类装载器载入类文件的字节码信息,经过解析后将其装入方法区.在方法区保存类的各种信息</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Point p = <span class="keyword">new</span> Point();</span><br></pre></td></tr></table></figure><p>Point 类首先被转载到JVM的方法区,包括类的基本信息和方法定义等.</p><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101605.png"><h3 id="JVM内存结构-栈区"><a href="#JVM内存结构-栈区" class="headerlink" title="JVM内存结构-栈区"></a>JVM内存结构-栈区</h3><p><code>栈</code>用于存放程序运行过程中当中所有的局部白能量.一个运行的java程序重开始到结束会有多次方法的调用.JVM会为每个方法的调用在栈中分配一个对应的空间,这个空间成为该<code>方法的栈桢</code>.一个栈桢对应一个正在调用中的方法,栈桢中存储了该方法的参数,局部变量等数据.当某一个方法调用完成后,其对应的栈桢将被清除.</p><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101606.png"><h3 id="JVM内存结构-堆区"><a href="#JVM内存结构-堆区" class="headerlink" title="JVM内存结构-堆区"></a>JVM内存结构-堆区</h3><p>JVM会在其内存空间中开辟一个成为”堆”的储存空间,这部分空间用于存储使用new关键字创建的对象</p><img src= "/img/loading.gif" data-lazy-src="/img/posts/note/101607.png">]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>SublimeText3输入法问题</title>
      <link href="ide/sublime/sublime-input/"/>
      <url>ide/sublime/sublime-input/</url>
      
        <content type="html"><![CDATA[<h3 id="方案1"><a href="#方案1" class="headerlink" title="方案1"></a>方案1</h3><p>很多新手朋友使用sublime,它是一个开源免费和轻量级的编辑器</p><p>但是在使用的过程中,可能会遇到SublimeText3默认不支持输入法跟随光标，这在输入中文的时候看起来不方便。</p><p>今天小编就教大家解决这个问题</p><p>进入<code>SublimeText3</code>在上面菜单栏里<code>Perferences</code>点击<code>PackageControl</code>，这样就会自动安装一个可支持插件的终端窗口。</p><p>安装完毕之后，按快捷键<code>ctrl+shift+p</code>会弹出终端窗口，输入<code>install package</code>（下方会有提示）。</p><p>然后输入<code>imesupport</code>安装这个插件，安装完毕后，重启<code>Sublime</code></p><p>如果上述方案仍然不能解决,请读下文</p><h3 id="方案2"><a href="#方案2" class="headerlink" title="方案2"></a>方案2</h3><div class="htmledit_views" id="content_views">                                            <p>我们使用Sublime时有个Bug就是输入文字时，输入法的框不会跟随光标。</p><p><img alt="" class="has" height="55" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190220142828949.png" width="633"></p><p>我们需要手动添加一个包 就能解决这个问题</p><p>第一步：下载<strong>IMESupport </strong>插件</p><p><strong>Github传送门</strong>：<a href="https://github.com/zcodes/IMESupport" rel="nofollow" data-token="0dce66f1378bbdf8a96f5c646cf34dce">https://github.com/zcodes/IMESupport</a>&nbsp;</p><p>如果你是用下载，下载后解压，注意双层文件夹的问题（两个同名文件夹，去掉外面的一个）。</p><p>第二步：<strong>放到package包下</strong>，这里必须手动添加依赖，不然不会生效</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="/img/posts/ide/sublime_packagecontrol.png"></p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="/img/posts/ide/sublime_packagecontrol2.png"></p><p>图中第一个是用package control安装的 没用。</p>                                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> sublime </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>23种设计模式汇总整理</title>
      <link href="java/javaold/java-design-mode23/"/>
      <url>java/javaold/java-design-mode23/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「炸斯特」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。</p><p>原文链接：<a href="https://blog.csdn.net/jason0539/article/details/44956775">https://blog.csdn.net/jason0539/article/details/44956775</a></p><h3 id="设计模式分为三大类："><a href="#设计模式分为三大类：" class="headerlink" title="设计模式分为三大类："></a>设计模式分为三大类：</h3><p><span style="color:#333333;"><strong>创建型模式</strong>，共五种：<a href="http://blog.csdn.net/jason0539/article/details/23020989" rel="nofollow" data-token="65341f6416632e8928f1cb4f28ba84dc">工厂方法模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/44976775" rel="nofollow" data-token="ba705163476f7ba1888b5eb7c77a1756">抽象工厂模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/23297037" rel="nofollow" data-token="3cf276cd0c7a9927a5c897ac055364d1">单例模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/44992733" rel="nofollow" data-token="762a8b411ddea056a5714a62cf96ffa7">建造者模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/23158081" rel="nofollow" data-token="a3d2c40eaa10681f49866ca0ddb2a95f">原型模式</a></span></p><p><span style="color:#333333;"><strong>结构型模式</strong>，共七种：<a href="http://blog.csdn.net/jason0539/article/details/22468457" rel="nofollow" data-token="594149357bd61da3d0c30e5134992493">适配器模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/22713711" rel="nofollow" data-token="f8c395644e3e802b3e5f97ad1a23e801">装饰者模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/22974405" rel="nofollow" data-token="1ed3eef1b4f4c9cbff2d062e18015830">代理模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/22775311" rel="nofollow" data-token="2de66c42766ed971360fcefdc521d133">外观模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/22568865" rel="nofollow" data-token="60df6a18382fe2ffc0e10fc14e0db6c7">桥接模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/22642281" rel="nofollow" data-token="9554be3e71acd97f8daed4d7911278d6">组合模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/22908915" rel="nofollow" data-token="42c7499405b69fd74792093bfabc5a07">享元模式</a>。</span></p><p><span style="color:#333333;"><strong>行为型模式</strong>，共十一种：</span><span style="color:#333333;"><a href="http://blog.csdn.net/jason0539/article/details/45007553" rel="nofollow" data-token="8782115ab39588abcdff2751255fd0a1">策略模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45037535" rel="nofollow" data-token="01ba7c04b06a4d25708f34c1b64aaac2">模板方法模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45055233" rel="nofollow" data-token="ede87ced00a8413a68bd03ac5d9acadc">观察者模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45070441" rel="nofollow" data-token="6e54db68efdc6577bba22716986a97ee">迭代子模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45091639" rel="nofollow" data-token="d7a67eb2ae9bcc7c411d1dff4884839c">责任链模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45110355" rel="nofollow" data-token="ca6578abc84fb6c6c445e40a45c9f1c7">命令模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45126489" rel="nofollow" data-token="db9c9edaa7f7d63f06d6077084aa1a00">备忘录模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45021055" rel="nofollow" data-token="c58457823044642182d6779ea6d5ff3f">状态模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45146271" rel="nofollow" data-token="6812d1acd968595cf5c06d403fd895ee">访问者模式</a>、<a href="http://blog.csdn.net/jason0539/article/details/45216585" rel="nofollow" data-token="0bfd29385f0c657f2026931e9129bc1f">中介者模式</a>、解释器模式</span><span style="color:#333333;">。</span></p><p><span style="color:#333333;">其实还有两类：并发型模式和线程池模式。</span></p><h2 id="设计模式的六大原则："><a href="#设计模式的六大原则：" class="headerlink" title="设计模式的六大原则："></a>设计模式的六大原则：</h2><h3 id="总原则－开闭原则"><a href="#总原则－开闭原则" class="headerlink" title="总原则－开闭原则"></a>总原则－开闭原则</h3><p>对扩展开放，对修改封闭。在程序需要进行拓展的时候，不能去修改原有的代码，而是要扩展原有代码，实现一个热插拔的效果。所以一句话概括就是：为了使程序的扩展性好，易于维护和升级。</p><p>想要达到这样的效果，我们需要使用接口和抽象类等，后面的具体设计中我们会提到这点。</p><h3 id="1、单一职责原则"><a href="#1、单一职责原则" class="headerlink" title="1、单一职责原则"></a>1、单一职责原则</h3><p>不要存在多于一个导致类变更的原因，也就是说每个类应该实现单一的职责，否则就应该把类拆分。</p><h3 id="2、里氏替换原则（Liskov-Substitution-Principle）"><a href="#2、里氏替换原则（Liskov-Substitution-Principle）" class="headerlink" title="2、里氏替换原则（Liskov Substitution Principle）"></a>2、里氏替换原则（Liskov Substitution Principle）</h3><p>任何基类可以出现的地方，子类一定可以出现。里氏替换原则是继承复用的基石，只有当衍生类可以替换基类，软件单位的功能不受到影响时，基类才能真正被复用，而衍生类也能够在基类的基础上增加新的行为。</p><p>里氏代换原则是对“开-闭”原则的补充。实现“开闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现，所以里氏代换原则是对实现抽象化的具体步骤的规范。里氏替换原则中，子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构，通过这个规范的接口与外界交互，子类不应该随便破坏它。</p><h3 id="3、依赖倒转原则（Dependence-Inversion-Principle）"><a href="#3、依赖倒转原则（Dependence-Inversion-Principle）" class="headerlink" title="3、依赖倒转原则（Dependence Inversion Principle）"></a>3、依赖倒转原则（Dependence Inversion Principle）</h3><p>面向接口编程，依赖于抽象而不依赖于具体。写代码时用到具体类时，不与具体类交互，而与具体类的上层接口交互。</p><h3 id="4、接口隔离原则（Interface-Segregation-Principle）"><a href="#4、接口隔离原则（Interface-Segregation-Principle）" class="headerlink" title="4、接口隔离原则（Interface Segregation Principle）"></a>4、接口隔离原则（Interface Segregation Principle）</h3><p>每个接口中不存在子类用不到却必须实现的方法，如果不然，就要将接口拆分。使用多个隔离的接口，比使用单个接口（多个接口方法集合到一个的接口）要好。</p><h3 id="5、迪米特法则（最少知道原则）（Demeter-Principle）"><a href="#5、迪米特法则（最少知道原则）（Demeter-Principle）" class="headerlink" title="5、迪米特法则（最少知道原则）（Demeter Principle）"></a>5、迪米特法则（最少知道原则）（Demeter Principle）</h3><p>一个类对自己依赖的类知道的越少越好。无论被依赖的类多么复杂，都应该将逻辑封装在方法的内部，通过public方法提供给外部。这样当被依赖的类变化时，才能最小的影响该类。</p><p>最少知道原则的另一个表达方式是：只与直接的朋友通信。类之间只要有耦合关系，就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。</p><h3 id="6、合成复用原则（Composite-Reuse-Principle）"><a href="#6、合成复用原则（Composite-Reuse-Principle）" class="headerlink" title="6、合成复用原则（Composite Reuse Principle）"></a>6、合成复用原则（Composite Reuse Principle）</h3><p>尽量首先使用合成/聚合的方式，而不是使用继承。</p>]]></content>
      
      
      
        <tags>
            
            <tag> summer </tag>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中的instanceof简析</title>
      <link href="java/javaold/java-instanceof/"/>
      <url>java/javaold/java-instanceof/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为博主原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接和本声明。  </p><p>本文链接：<a href="https://blog.csdn.net/liranke/article/details/5574791">https://blog.csdn.net/liranke/article/details/5574791</a>  </p><h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出，这个对象是否是这个特定类或者是它的子类的一个实例。<br> 用法：<br>result = object instanceof class<br>参数：<br>Result：布尔类型。<br>Object：必选项。任意对象表达式。<br>Class：必选项。任意已定义的对象类。<br>说明：<br>如果 object 是 class 的一个实例，则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例，或者 object 是 null，则返回 false。  </p><h3 id="例子如下："><a href="#例子如下：" class="headerlink" title="例子如下："></a>例子如下：</h3><pre><code class="java">package com.instanceoftest;          interface A&#123;&#125;   class B implements A&#123;      &#125;   class C extends B &#123;      &#125;      class instanceoftest &#123;    public static void main(String[] args)&#123;       A a=null;       B b=null;       boolean res;             System.out.println(&quot;instanceoftest test case 1: ------------------&quot;);         res = a instanceof A;         System.out.println(&quot;a instanceof A: &quot; + res);                 res = b instanceof B;         System.out.println(&quot;b instanceof B: &quot; + res);               System.out.println(&quot;/ninstanceoftest test case 2: ------------------&quot;);         a=new B();       b=new B();             res = a instanceof A;       System.out.println(&quot;a instanceof A: &quot; + res);             res = a instanceof B;       System.out.println(&quot;a instanceof B: &quot; + res);         res = b instanceof A;       System.out.println(&quot;b instanceof A: &quot; + res);             res = b instanceof B;       System.out.println(&quot;b instanceof B: &quot; + res);            System.out.println(&quot;/ninstanceoftest test case 3: ------------------&quot;);       B b2=(C)new C();             res = b2 instanceof A;       System.out.println(&quot;b2 instanceof A: &quot; + res);             res = b2 instanceof B;       System.out.println(&quot;b2 instanceof B: &quot; + res);             res = b2 instanceof C;       System.out.println(&quot;b2 instanceof C: &quot; + res);    &#125;  &#125;      </code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中的内存浅析</title>
      <link href="java/javaold/java-ram/"/>
      <url>java/javaold/java-ram/</url>
      
        <content type="html"><![CDATA[<p>Java的内存需要划分成为5个部分</p><h3 id="1-栈-stack"><a href="#1-栈-stack" class="headerlink" title="1. 栈(stack):"></a>1. 栈(stack):</h3><p>存放的都是方法中的局部变量.方法的运行一定要在栈当中</p><p>局部变量: 方法的参数,或者是方法{}内部的变量</p><p>作用域:一旦超出作用域,立刻从栈内存当中消失</p><h3 id="2-堆-heap"><a href="#2-堆-heap" class="headerlink" title="2. 堆(heap):"></a>2. 堆(heap):</h3><p>凡是new出来的东西,都在堆当中</p><p>堆内存里面的东西都有一个地址值.规则:<br>    如果是整数       默认为0<br>    如果是浮点数      默认为0.0<br>    如果是字符       默认为’\u0000’<br>    如果是布尔       默认为false<br>    如果是引用类型     默认为null</p><h3 id="3-方法区-method-area"><a href="#3-方法区-method-area" class="headerlink" title="3. 方法区(method area):"></a>3. 方法区(method area):</h3><p>存储.class相关信息,包含方法的信息</p><h3 id="4-本地方法栈-native-method-stack"><a href="#4-本地方法栈-native-method-stack" class="headerlink" title="4. 本地方法栈(native method stack):"></a>4. 本地方法栈(native method stack):</h3><p>与操作系统相关</p><h3 id="5-寄存器-pc-register"><a href="#5-寄存器-pc-register" class="headerlink" title="5. 寄存器(pc register):"></a>5. 寄存器(pc register):</h3><p>与CPU相关</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java设计模式之单例模式</title>
      <link href="java/javaold/java-single-case/"/>
      <url>java/javaold/java-single-case/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「炸斯特」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。</p><p>原文链接：<a href="https://blog.csdn.net/jason0539/article/details/23297037">https://blog.csdn.net/jason0539/article/details/23297037</a></p><h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>java中单例模式是一种常见的设计模式，单例模式的写法有好几种，这里主要介绍两种：懒汉式单例、饿汉式单例。</p><h3 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h3><p>1、单例类只能有一个实例。<br>2、单例类必须自己创建自己的唯一实例。<br>3、单例类必须给所有其他对象提供这一实例</p><p>单例模式确保某个类只有一个实例，而且自行实例化并向整个系统提供这个实例。在计算机系统中，线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机，但只能有一个Printer Spooler，以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口，系统应当集中管理这些通信端口，以避免一个通信端口同时被两个请求同时调用。总之，选择单例模式就是为了避免不一致状态，避免政出多头。</p><h3 id="一、懒汉式单例"><a href="#一、懒汉式单例" class="headerlink" title="一、懒汉式单例"></a>一、懒汉式单例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//懒汉式单例类.在第一次调用的时候实例化自己 </span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Singleton single=<span class="keyword">null</span>;</span><br><span class="line">    <span class="comment">//静态工厂方法 </span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">         <span class="keyword">if</span> (single == <span class="keyword">null</span>) &#123;  </span><br><span class="line">             single = <span class="keyword">new</span> Singleton();</span><br><span class="line">         &#125;  </span><br><span class="line">        <span class="keyword">return</span> single;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="二、饿汉式单例"><a href="#二、饿汉式单例" class="headerlink" title="二、饿汉式单例"></a>二、饿汉式单例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;饿汉式单例类.在类初始化时，已经自行实例化 </span><br><span class="line">public class Singleton1 &#123;</span><br><span class="line">    private Singleton1() &#123;&#125;</span><br><span class="line">    private static final Singleton1 single &#x3D; new Singleton1();</span><br><span class="line">    &#x2F;&#x2F;静态工厂方法 </span><br><span class="line">    public static Singleton1 getInstance() &#123;</span><br><span class="line">        return single;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="1、线程安全："><a href="#1、线程安全：" class="headerlink" title="1、线程安全："></a>1、线程安全：</h3><p>饿汉式天生就是线程安全的，可以直接用于多线程而不会出现问题，</p><p>懒汉式本身是非线程安全的，为了实现线程安全有几种写法，分别是上面的1、2、3，这三种实现在资源加载和性能方面有些区别。</p><h3 id="2、资源加载和性能："><a href="#2、资源加载和性能：" class="headerlink" title="2、资源加载和性能："></a>2、资源加载和性能：</h3><p>饿汉式在类创建的同时就实例化一个静态对象出来，不管之后会不会使用这个单例，都会占据一定的内存，但是相应的，在第一次调用时速度也会更快，因为其资源已经初始化完成，</p><p>而懒汉式顾名思义，会延迟加载，在第一次使用该单例的时候才会实例化对象出来，第一次调用时要做初始化，如果要做的工作比较多，性能上会有些延迟，之后就和饿汉式一样了。</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java笔记01-数组相关</title>
      <link href="java/javase/note/note01/"/>
      <url>java/javase/note/note01/</url>
      
        <content type="html"><![CDATA[<h3 id="数组相关"><a href="#数组相关" class="headerlink" title="数组相关"></a>数组相关</h3><p>数组的创建</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">数据类型[] 数组名称 = <span class="keyword">new</span> 数据类型[数组的长度]</span><br></pre></td></tr></table></figure><p>其中数据类型可以为任意类型</p><p>数组的访问</p><p>• 调用数组的length属性可以获取数组的长度：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> len = arr.length;</span><br></pre></td></tr></table></figure><p>• 可以通过下标的方式访问数组中的每一个元素。  </p><p>需要注意的是：数组的下标从0开始，对于长度为n的数组，下标的范围是0~n-1。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> tmp = a[<span class="number">2</span>];</span><br></pre></td></tr></table></figure><p>二维数组</p><p>• Java允许使用多维数组，其中最常见的就是二维数组。</p><p>• 二维数组就是由一维数组组成的数组，其元素是一维数组。</p><p>• 二维数组定义时需要两个中括号，方式如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[][] arr = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">2</span>][<span class="number">3</span>];</span><br><span class="line"><span class="keyword">int</span>[][] arr = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">3</span>][];</span><br></pre></td></tr></table></figure><p>• 定义二维数组arr以后， arr是二维数组，arr[i]是一维数组，arr[i][j]是数<br>据。</p><p>其中，最左边的中括号里面必须有长度。</p>]]></content>
      
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于java语法的各种坑</title>
      <link href="java/javase/java-bug/"/>
      <url>java/javase/java-bug/</url>
      
        <content type="html"><![CDATA[<h3 id="字符串相关"><a href="#字符串相关" class="headerlink" title="字符串相关"></a>字符串相关</h3><ul><li><p>单引号不能定义多个字符串</p></li><li><p>字符串判断相等最好用<code>==</code>:<br>  (Scanner输入进的字符串不能这么判断)<br>  解释:<code>==</code>不仅仅比较值还比较内存地址</p></li></ul><h3 id="类型相关"><a href="#类型相关" class="headerlink" title="类型相关"></a>类型相关</h3><ul><li>数组不能嵌套</li><li>数组中的类型要一样,提前定义好</li><li>数组不能直接增加</li><li>函数的返回值类型要提前声明好</li></ul><h3 id="OOP"><a href="#OOP" class="headerlink" title="OOP"></a>OOP</h3><ul><li>类不能进行多继承</li><li>接口可以多实现,来补充了类的多继承</li></ul><h3 id="容器类数据"><a href="#容器类数据" class="headerlink" title="容器类数据"></a>容器类数据</h3><ul><li><p>List 集合就是python中的列表list</p></li><li><p>Map 集合就是python中的字典dict</p></li><li><p>Set 集合就是python中的集合set</p></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>在idea中使用git管理你的项目</title>
      <link href="git/git-idea/"/>
      <url>git/git-idea/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>idea是十分智能的Java集成开发环境</p><p>而我们在用idea写项目的时候经常遇到版本控制的问题,而git工具如果你只会在终端中的git命令来进行控制,可能会使得效率低下</p><p>今天小编就教大家在idea中使用git</p><h3 id="首先创建一个项目"><a href="#首先创建一个项目" class="headerlink" title="首先创建一个项目"></a>首先创建一个项目</h3><p><img src= "/img/loading.gif" data-lazy-src="1.png" alt="开启"><br>点击create new projects<br><img src= "/img/loading.gif" data-lazy-src="2.png" alt="创建项目"><br>这里选择默认的就可以,关于jdk的安装可以参考<a href="https://victorfengming.gitee.io/blog/ubuntu-install-jdk/">ubuntu系统下Java环境JDK的安装</a>和<a href="https://victorfengming.gitee.io/blog/deepin-install-jdk/">Deepin下java开发环境部署</a></p><p><img src= "/img/loading.gif" data-lazy-src="3.png" alt="创建项目2"></p><p>这里是询问我们需不需要从模板创建项目,直接点击next即可</p><p><img src= "/img/loading.gif" data-lazy-src="4.png" alt="创建项目"></p><p>这里填写项目的名称和位置</p><p>填完后,点击finish即可</p><h3 id="在idea中登录你的github"><a href="#在idea中登录你的github" class="headerlink" title="在idea中登录你的github"></a>在idea中登录你的github</h3><p>刚刚创建的Java项目是这样的<br><img src= "/img/loading.gif" data-lazy-src="5.png" alt="创建项目"></p><p>我们需要点击设置<br><img src= "/img/loading.gif" data-lazy-src="6.png" alt="setting"></p><p>在设置中搜索git<br><img src= "/img/loading.gif" data-lazy-src="7.png" alt="git"></p><p>选择git下面的github<br><img src= "/img/loading.gif" data-lazy-src="8.png" alt="git"></p><p>在右边点击<code>+</code>号<br><img src= "/img/loading.gif" data-lazy-src="9.png" alt="github"></p><p>输入你的github的账号和密码<br><img src= "/img/loading.gif" data-lazy-src="10.png" alt="github"></p><p>这里可以勾选ssh协议,关于ssh的配置可以参考:<a href="https://victorfengming.gitee.io/blog/github-generate-ssh/">git生成SSH并提交</a></p><p>配置好后<br>点击OK即可</p><p><strong>注意</strong>:<br>登录github之后<br>项目中文件的颜色将会变为<code>褐色</code></p><h3 id="创建一个github仓库-并将项目交给git来管理"><a href="#创建一个github仓库-并将项目交给git来管理" class="headerlink" title="创建一个github仓库,并将项目交给git来管理"></a>创建一个github仓库,并将项目交给git来管理</h3><p>点击菜单栏的VCS-&gt;Import into Version Control-&gt;Create Git Repository</p><p><img src= "/img/loading.gif" data-lazy-src="11.png" alt="交给git管理"></p><p>这里我们选中项目文件夹即可</p><p><img src= "/img/loading.gif" data-lazy-src="12.png" alt="仓库"></p><h3 id="新建一个类-测试运行"><a href="#新建一个类-测试运行" class="headerlink" title="新建一个类,测试运行"></a>新建一个类,测试运行</h3><p><img src= "/img/loading.gif" data-lazy-src="13.png" alt="仓库"><br>创建好了一个空类</p><p><img src= "/img/loading.gif" data-lazy-src="14.png" alt="仓库"><br>写一个简单的helloworld代码</p><p><img src= "/img/loading.gif" data-lazy-src="15.png" alt="仓库"></p><p>运行一下,测试效果<br><img src= "/img/loading.gif" data-lazy-src="16.png" alt="仓库"></p><p>运行成功</p><h3 id="添加到本地-add"><a href="#添加到本地-add" class="headerlink" title="添加到本地(add)"></a>添加到本地(add)</h3><p>注意上面的文件名称为<code>红色</code>的</p><p>然后我们在项目文件夹上面右键-&gt;选择Git-&gt;add</p><p><img src= "/img/loading.gif" data-lazy-src="17.png" alt="仓库"></p><p>add 之后</p><p>项目中文件的颜色将会变为<code>绿色</code></p><p><img src= "/img/loading.gif" data-lazy-src="18.png" alt="仓库"></p><h3 id="提交的本地仓库-commit"><a href="#提交的本地仓库-commit" class="headerlink" title="提交的本地仓库(commit)"></a>提交的本地仓库(commit)</h3><p>我们在项目文件夹上面右键-&gt;选择Git-&gt;Commit Directory</p><p><img src= "/img/loading.gif" data-lazy-src="19.png" alt="仓库"></p><p>这里填写一些我们关于这此提交的说明或注释<br><img src= "/img/loading.gif" data-lazy-src="20.png" alt="仓库"></p><p>commit之后<br>项目中文件的颜色将会变为<code>白色</code><br><img src= "/img/loading.gif" data-lazy-src="21.png" alt="仓库"></p><h3 id="推本地存储库到远程仓库-push"><a href="#推本地存储库到远程仓库-push" class="headerlink" title="推本地存储库到远程仓库(push)"></a>推本地存储库到远程仓库(push)</h3><p>首先我们需要在github中创建一个存储库</p><p><img src= "/img/loading.gif" data-lazy-src="22.png" alt="仓库"></p><p>关于git可以参考:<a href="https://victorfengming.gitee.io/git/progit-min/">git个人整理总结</a>,关于github使用,可以参考:<a href="https://blog.csdn.net/nyist327/article/details/38900721">GitHub使用教程</a></p><p><img src= "/img/loading.gif" data-lazy-src="23.png" alt="仓库"><br>repository创建好后,复制远程仓库的地址,这里我们使用的是SSH协议(当然你也可以使用HTTPS的协议)</p><p>关于ssh的配置可以参考:<a href="https://victorfengming.gitee.io/blog/github-generate-ssh/">git生成SSH并提交</a></p><p><img src= "/img/loading.gif" data-lazy-src="24.png" alt="仓库"></p><p>然后我们回到idea中</p><p>在项目文件夹上面右键-&gt;选择Git-&gt;Repository-&gt;Push (或者按快捷键Ctrl+shift+K)</p><p><img src= "/img/loading.gif" data-lazy-src="25.png" alt="打开push"></p><p>在弹出的窗口中点击define remote<br><img src= "/img/loading.gif" data-lazy-src="26.png" alt="remote"></p><p>这里我们需要填写名称和远程仓库的地址<br>直接将刚才复制好的远程仓库的地址粘贴进来即可<br><img src= "/img/loading.gif" data-lazy-src="27.png" alt="ssh地址"></p><p>点击OK稍等片刻<br><img src= "/img/loading.gif" data-lazy-src="28.png" alt="配置remote"></p><p>右面会出现刚刚commit后的本地仓库中的文件列表<br><img src= "/img/loading.gif" data-lazy-src="29.png" alt="push文件列表"></p><p>点击Push即可推到远程仓库中<br><img src= "/img/loading.gif" data-lazy-src="30.png" alt="状态栏"><br>在idea下面的状况栏中可以查看进度,和分支的一些详细信息</p><p>回到github中,刷新你的存储库的页面,会发现刚才push的文件已经存到你的远程仓库中了</p><p><img src= "/img/loading.gif" data-lazy-src="31.png" alt="远程仓库"></p><h3 id="克隆远程的git项目到本地-clone"><a href="#克隆远程的git项目到本地-clone" class="headerlink" title="克隆远程的git项目到本地(clone)"></a>克隆远程的git项目到本地(clone)</h3><p>先在github中复制你的远程仓库地址(这里使用sh协议)</p><p><img src= "/img/loading.gif" data-lazy-src="32.png" alt="状态栏"></p><p>然后回到idea中</p><p>点击菜单栏中 VCS -&gt; check from version control-&gt; Git</p><p><img src= "/img/loading.gif" data-lazy-src="33.png" alt="状态栏"></p><p>将你的url粘贴进去<br><img src= "/img/loading.gif" data-lazy-src="34.png" alt="状态栏"></p><p>点击Test进行测试连接,如果现实connection successful 即为连接成功<br><img src= "/img/loading.gif" data-lazy-src="35.png" alt="状态栏"></p><p>然后点击clone 即可克隆到本地</p><p><img src= "/img/loading.gif" data-lazy-src="36.png" alt="状态栏"><br>这里克隆成功后会询问你要不要在idea中打开它</p><p>这里我们选择取消即可,然后重新打开刚刚克隆的项目即可</p><h3 id="拉取远程的git项目到本地-pull"><a href="#拉取远程的git项目到本地-pull" class="headerlink" title="拉取远程的git项目到本地(pull)"></a>拉取远程的git项目到本地(pull)</h3><p>如果你想要push你的修改,但是这是其他人也对项目进行了修改,这就有可能会导致merge失败,所以在你push前,需要先pull拉去最新的版本,再进行push你的提交</p><p>进入idea中</p><p>在项目文件夹上面右键-&gt;选择Git-&gt;Repository-&gt;Pull </p><p><img src= "/img/loading.gif" data-lazy-src="37.png" alt="状态栏"></p><p>这里点击pull即可拉取远程仓库的最新修改<br><img src= "/img/loading.gif" data-lazy-src="38.png" alt="状态栏"></p><p>这样,在你下一次push 的时候,就可以选择哪个分支来处理版本之间的冲突了</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Git </tag>
            
            <tag> idea </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python实现修改图片尺寸</title>
      <link href="python/self_tool/python-change-pic-size/"/>
      <url>python/self_tool/python-change-pic-size/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>很多小伙伴从网上找的图片可能图片尺寸与自己的需求不符合</p><p>今天小编就教大家使用python写一个简单脚本程序实现修改图片的尺寸</p><h3 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h3><p>首先我们需要python环境,它的安装可以参考:<a href="https://victorfengming.gitee.io/blog/python-install-window/">python安装以及版本检测</a></p><p>其次我们还需要安装一个python图形化的库PIL</p><p>PIL的安装,这里我们使用pip来进行安装,关于pip可以参考:<a href="https://victorfengming.gitee.io/blog/python-install-pip/">Python pip 安装与使用</a></p><p>pip安装好后,在终端中执行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install PIL</span><br></pre></td></tr></table></figure><p>等待安装完成即可</p><p>如果安装了pycharm的同学可以在设置中的解释器栏里面直接进行安装</p><p>这里小编推荐使用<a href="https://victorfengming.gitee.io/blog/jetbrains-pycharm-introduce/">pycharm</a>进行安装</p><p>关于它的安装可以参考:<a href="https://victorfengming.gitee.io/blog/pycharm-install/">PyCharm的安装以及破解</a></p><h3 id="源码参考"><a href="#源码参考" class="headerlink" title="源码参考"></a>源码参考</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by victor</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;更改图片尺寸&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> os.path</span><br><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">filein: 输入图片</span></span><br><span class="line"><span class="string">fileout: 输出图片</span></span><br><span class="line"><span class="string">width: 输出图片宽度</span></span><br><span class="line"><span class="string">height:输出图片高度</span></span><br><span class="line"><span class="string">type:输出图片类型（png, gif, jpeg...）</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">ResizeImage</span>(<span class="params">filein, fileout, width, height, <span class="built_in">type</span></span>):</span></span><br><span class="line">  img = Image.<span class="built_in">open</span>(filein)</span><br><span class="line">  out = img.resize((width, height),Image.ANTIALIAS)</span><br><span class="line">  <span class="comment">#resize image with high-quality</span></span><br><span class="line">  out.save(fileout, <span class="built_in">type</span>)</span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">  filein = <span class="string">r&#x27;./image/plane.png&#x27;</span></span><br><span class="line">  fileout = <span class="string">r&#x27;./image/planesm.png&#x27;</span></span><br><span class="line">  width = <span class="number">50</span></span><br><span class="line">  height = <span class="number">50</span></span><br><span class="line">  <span class="built_in">type</span> = <span class="string">&#x27;png&#x27;</span></span><br><span class="line">  ResizeImage(filein, fileout, width, height, <span class="built_in">type</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="相关推荐"><a href="#相关推荐" class="headerlink" title="相关推荐"></a>相关推荐</h3><p>关于Python相关内容感兴趣的读者可查看专题：<br>《<a target="_blank" href="//www.jb51.net/Special/645.htm">Python图片操作技巧总结</a>》<br>《<a target="_blank" href="//www.jb51.net/Special/663.htm">Python数据结构与算法教程</a>》<br>《<a target="_blank" href="//www.jb51.net/Special/648.htm">Python Socket编程技巧总结</a>》<br>《<a target="_blank" href="//www.jb51.net/Special/642.htm">Python函数使用技巧总结</a>》<br>《<a target="_blank" href="//www.jb51.net/Special/636.htm">Python字符串操作技巧汇总</a>》<br>《<a target="_blank" href="//www.jb51.net/Special/520.htm">Python入门与进阶经典教程</a>》<br>《<a target="_blank" href="//www.jb51.net/Special/516.htm">Python文件与目录操作技巧汇总</a>》</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>java,python,php 中的数组简识</title>
      <link href="java/javaold/array/"/>
      <url>java/javaold/array/</url>
      
        <content type="html"><![CDATA[<h3 id="python-列表，元素，字典"><a href="#python-列表，元素，字典" class="headerlink" title="python 列表，元素，字典"></a>python 列表，元素，字典</h3><p>数组三种模式:列表(list),元组(tuple),字典(dict)，均支持遍历，也支持迭代</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">demo1 = [<span class="string">&#x27;a&#x27;</span>,<span class="string">&#x27;b&#x27;</span>,<span class="string">&#x27;c&#x27;</span>,<span class="string">&#x27;d&#x27;</span>]           <span class="comment"># 列表</span></span><br><span class="line">demo2 = (<span class="string">&#x27;a&#x27;</span>,<span class="string">&#x27;b&#x27;</span>,<span class="string">&#x27;c&#x27;</span>,<span class="string">&#x27;d&#x27;</span>)           <span class="comment"># 元组</span></span><br><span class="line">demo3 = &#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;kurt&quot;</span>,<span class="string">&quot;age&quot;</span>:<span class="number">18</span>,<span class="string">&quot;sex&quot;</span>,<span class="number">1</span>&#125; <span class="comment"># 字典</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># for循环遍历列表/元组里面的数据</span></span><br><span class="line"><span class="keyword">for</span> item <span class="keyword">in</span> demo1:</span><br><span class="line">    <span class="built_in">print</span> item</span><br><span class="line"></span><br><span class="line"><span class="comment"># for循环遍历列表/元组里面的索引</span></span><br><span class="line"><span class="keyword">for</span> key <span class="keyword">in</span> xrange(<span class="number">0</span>, <span class="built_in">len</span>(demo1)):</span><br><span class="line">    <span class="built_in">print</span> key, demo1[key]</span><br><span class="line"></span><br><span class="line"><span class="comment"># for循环遍历字典的数据</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># key</span></span><br><span class="line"><span class="keyword">for</span> key <span class="keyword">in</span> demo3:</span><br><span class="line">    <span class="built_in">print</span> key</span><br><span class="line"></span><br><span class="line"><span class="comment"># value</span></span><br><span class="line"><span class="keyword">for</span> value <span class="keyword">in</span> demo3.values():</span><br><span class="line">    <span class="built_in">print</span> value</span><br><span class="line"></span><br><span class="line"><span class="comment"># key&amp;values</span></span><br><span class="line"><span class="keyword">for</span> item <span class="keyword">in</span> demo3.items():</span><br><span class="line">    <span class="built_in">print</span> item <span class="comment"># tuple</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># python的iteritems,iterkeys,itervalues。作用相似，返回的是一个迭代器。迭代器可以用next来输出</span></span><br><span class="line">rs = demo1.iteritems()</span><br><span class="line"><span class="built_in">print</span> rs.<span class="built_in">next</span>()</span><br><span class="line"><span class="built_in">print</span> rs.<span class="built_in">next</span>()</span><br></pre></td></tr></table></figure><h3 id="php数组"><a href="#php数组" class="headerlink" title="php数组"></a>php数组</h3><p>php数组支持一维数组和多维数组的混搭。数组的value可以是任意类型。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 关联数组。需要指定key。</span></span><br><span class="line"><span class="variable">$arr1</span> = <span class="keyword">array</span>(</span><br><span class="line">    <span class="string">&quot;name&quot;</span>=&gt;<span class="string">&quot;kurt&quot;</span>,</span><br><span class="line">    <span class="string">&quot;age&quot;</span> =&gt;<span class="number">18</span>,</span><br><span class="line">    <span class="string">&quot;sex&quot;</span> =&gt;<span class="number">1</span></span><br><span class="line">);</span><br><span class="line"><span class="comment">// 索引数组，key会自动以0开始。</span></span><br><span class="line"><span class="variable">$arr2</span> = [ <span class="number">12</span>, <span class="number">34</span>,<span class="number">2</span>,<span class="number">41</span>,<span class="number">5</span> ]; <span class="comment">// 简写数组</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 多维数组</span></span><br><span class="line"><span class="variable">$arr3</span> = [</span><br><span class="line">    <span class="string">&#x27;http&#x27;</span>  =&gt; [<span class="string">&#x27;nginx&#x27;</span>,<span class="string">&#x27;apache&#x27;</span>,<span class="string">&#x27;iis&#x27;</span>],</span><br><span class="line">    <span class="string">&#x27;cache&#x27;</span> =&gt; [<span class="string">&#x27;redis&#x27;</span>,<span class="string">&#x27;memcache&#x27;</span>],</span><br><span class="line">    <span class="string">&#x27;database&#x27;</span> =&gt; [<span class="string">&#x27;mysql&#x27;</span>,<span class="string">&#x27;orecal&#x27;</span>,<span class="string">&#x27;DB2&#x27;</span>,<span class="string">&#x27;mssql&#x27;</span>],</span><br><span class="line">    <span class="string">&#x27;remark&#x27;</span> =&gt; <span class="string">&#x27;多维数组下面的value是相对独立&#x27;</span></span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="comment">// 遍历</span></span><br><span class="line"><span class="keyword">foreach</span> (<span class="variable">$arr1</span> <span class="keyword">as</span> <span class="variable">$k</span>=&gt;<span class="variable">$v</span>)</span><br><span class="line">&#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="variable">$k</span>,<span class="variable">$v</span> ; <span class="comment">// key &amp;&amp; value</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="java数组"><a href="#java数组" class="headerlink" title="java数组"></a>java数组</h3><p>数组中可以存放任意类型的数据，但是同一个数组存放的元素必须一致。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"># 声明并创建可以存3个整数的数组</span><br><span class="line">int[] arr0 &#x3D; new int[3] ; </span><br><span class="line"># 先声明后创建可以存3个整数数组</span><br><span class="line">int[] arr1; </span><br><span class="line">arr1&#x3D;new int[3]; </span><br><span class="line"></span><br><span class="line"># 数组赋值。初始化数组的时候会赋值为0.</span><br><span class="line">arr0[0] &#x3D; &#39;a&#39;;</span><br><span class="line">arr0[1] &#x3D; &#39;b&#39;;</span><br><span class="line">arr0[2] &#x3D; &#39;c&#39;;</span><br><span class="line"># arr0[3] &#x3D; &#39;d&#39;; # 报错，超出索引</span><br><span class="line"></span><br><span class="line"># 数组静态初始化。。</span><br><span class="line">int[] arr2 &#x3D; new int[]&#123;1,2,3,4&#125;; # 声明并初始化并复制</span><br><span class="line">int[] arr3 &#x3D; &#123;1,2,3,4&#125;; # 声明后直接复制</span><br><span class="line"></span><br><span class="line"># for循环遍历数组</span><br><span class="line">for (int i &#x3D; 0; i &lt;arr0.length ; i++) </span><br><span class="line">&#123;</span><br><span class="line">    System.out.print(arr0[i]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> php </tag>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>送你一些实用的工具,收藏起来留着用</title>
      <link href="unclass/programmer-tools/"/>
      <url>unclass/programmer-tools/</url>
      
        <content type="html"><![CDATA[<div class="htmledit_views" id="content_views">                                            <h1 id="main-toc"><a name="t0"></a><strong>目录</strong></h1><p id="1%E3%80%81%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E-toc" style="margin-left:0px;"><a href="#1%E3%80%81%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E" rel="nofollow" data-token="123d44a3d28accd7dcf80810b9256338" target="_self">1、搜索引擎</a></p><p id="2%E3%80%81PPT-toc" style="margin-left:0px;"><a href="#2%E3%80%81PPT" rel="nofollow" data-token="cecd46360e8c395e699117f6e3593dee" target="_self">2、PPT</a></p><p id="3%E3%80%81%E5%9B%BE%E7%89%87%E6%93%8D%E4%BD%9C-toc" style="margin-left:0px;"><a href="#3%E3%80%81%E5%9B%BE%E7%89%87%E6%93%8D%E4%BD%9C" rel="nofollow" data-token="8d1ae155d1d35583b07122569bda49c2" target="_self">3、图片操作</a></p><p id="4%E3%80%81%E6%96%87%E4%BB%B6%E5%85%B1%E4%BA%AB-toc" style="margin-left:0px;"><a href="#4%E3%80%81%E6%96%87%E4%BB%B6%E5%85%B1%E4%BA%AB" rel="nofollow" data-token="fd375cea8501d5da8e9260d315f8d681" target="_self">4、文件共享</a></p><p id="5%E3%80%81%E5%BA%94%E5%B1%8A%E7%94%9F%E6%8B%9B%E8%81%98-toc" style="margin-left:0px;"><a href="#5%E3%80%81%E5%BA%94%E5%B1%8A%E7%94%9F%E6%8B%9B%E8%81%98" rel="nofollow" data-token="2a3e197811b9d85a71a1ae0788dd8d1c" target="_self">5、应届生招聘</a></p><p id="6%E3%80%81%E7%A8%8B%E5%BA%8F%E5%91%98%E9%9D%A2%E8%AF%95%E9%A2%98%E5%BA%93-toc" style="margin-left:0px;"><a href="#6%E3%80%81%E7%A8%8B%E5%BA%8F%E5%91%98%E9%9D%A2%E8%AF%95%E9%A2%98%E5%BA%93" rel="nofollow" data-token="08426b0271b05c5a11fd192697612401" target="_self">6、程序员面试题库</a></p><p id="7%E3%80%81%E5%8A%9E%E5%85%AC%E3%80%81%E5%BC%80%E5%8F%91%E8%BD%AF%E4%BB%B6-toc" style="margin-left:0px;"><a href="#7%E3%80%81%E5%8A%9E%E5%85%AC%E3%80%81%E5%BC%80%E5%8F%91%E8%BD%AF%E4%BB%B6" rel="nofollow" data-token="17790f05034573a7a6f65c2ff7acf6eb" target="_self">7、办公、开发软件</a></p><p id="8%E3%80%81%E9%AB%98%E6%B8%85%E5%9B%BE%E7%89%87%E3%80%81%E8%A7%86%E9%A2%91%E7%B4%A0%E6%9D%90%E7%BD%91%E7%AB%99%C2%A0-toc" style="margin-left:0px;"><a href="#8%E3%80%81%E9%AB%98%E6%B8%85%E5%9B%BE%E7%89%87%E3%80%81%E8%A7%86%E9%A2%91%E7%B4%A0%E6%9D%90%E7%BD%91%E7%AB%99%C2%A0" rel="nofollow" data-token="5c1a85f67eaf10c80341279b0ee2dce3" target="_self">8、高清图片、视频素材网站&nbsp;</a></p><p id="9%E3%80%81%E9%A1%B9%E7%9B%AE%E5%BC%80%E6%BA%90-toc" style="margin-left:0px;"><a href="#9%E3%80%81%E9%A1%B9%E7%9B%AE%E5%BC%80%E6%BA%90" rel="nofollow" data-token="dcfbe8bb54975bdbf0d600972a74edc0" target="_self">9、项目开源</a></p><p id="10%E3%80%81%E5%9C%A8%E7%BA%BF%E5%B7%A5%E5%85%B7%E5%AE%9D%E5%85%B8%E5%A4%A7%E5%85%A8-toc" style="margin-left:0px;"><a href="#10%E3%80%81%E5%9C%A8%E7%BA%BF%E5%B7%A5%E5%85%B7%E5%AE%9D%E5%85%B8%E5%A4%A7%E5%85%A8" rel="nofollow" data-token="75c64279ebaa772468f75a9b9794efa2" target="_self">10、在线工具宝典大全</a></p><hr id="hr-toc"><p style="text-indent:33px;">程序员开发需要具备良好的信息检索能力，为了备忘（收藏夹真是满了），将开发过程中常用的网站进行整理。</p><h1 id="1%E3%80%81%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E"><a name="t1"></a>1、搜索引擎</h1><h2 id="1.1%E3%80%81%E7%A7%98%E8%BF%B9%E6%90%9C%E7%B4%A2"><a name="t2"></a><strong>1.1、秘迹搜索</strong></h2><p style="text-indent:33px;">一款无敌有良心、无敌安全的搜索引擎，不会收集私人信息，保护私隐，没有Cookie，并且秘迹搜索聚合了百度、360、Bing、搜狗等搜索结果。</p><p style="text-align:center;"><img alt="" class="has" height="196" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190829095508389.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70" width="600"></p><p style="text-indent:33px;">网站：<a href="https://mijisou.com" rel="nofollow" data-token="ec966c202b65efb2a2de9a77d2e28c40">https://mijisou.com</a></p><h2 id="1.2%E3%80%81%E5%B0%8F%E7%99%BD%E7%9B%98"><a name="t3"></a><strong>1.2、小白盘</strong></h2><p style="text-indent:33px;">度盘资源搜索的网站，能够搜索电影、电视剧、小说、音乐等资源（<strong>注意：评论区很多小伙伴说小白盘有毒，我用谷歌浏览器搜索过几次并无大碍，请慎用！</strong>）</p><p style="text-align:center;"><img alt="" class="has" height="397" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190829095422704.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70" width="600"></p><p style="text-indent:33px;">网站：<a href="https://www.xiaobaipan.com" rel="nofollow" data-token="32a5c87612da8cce99422c1088011aeb">https://www.xiaobaipan.com</a></p><h2 style="text-indent:0px;"><a name="t4"></a><strong>1.3、</strong>&nbsp;<strong>DogeDoge搜索</strong></h2><p style="text-indent:33px;">DogeDoge搜索，中文名多吉搜索，一个绝赞的民间高手开发的搜索引擎，传说完全可以替代百度搜索<strong>，</strong>百度首页几乎都是广告，而 DogeDoge搜索一个广告都没有，搜索答案侧重于知乎、博客园、CSDN等，实在良心，搜索结果和谷歌差不多，非常适合那些无法科学上网的朋友。</p><p style="text-align:center;"><img alt="" class="has" height="344" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20191011132627231.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="1000"></p><p style="text-indent:33px;">网站：<a href="https://www.dogedoge.com/" rel="nofollow" data-token="0ca0755c95ac935a2c178e41b6ba5261">https://www.dogedoge.com/</a></p><h1 id="2%E3%80%81PPT"><a name="t5"></a>2、PPT</h1><h2 id="2.1%E3%80%81%E4%BC%98%E5%93%81PPT"><a name="t6"></a><strong>2.1、优品PPT</strong></h2><p style="text-indent:33px;">高品质免费PPT模板下载网站，比第一PPT质量高很多。</p><p style="text-align:center;"><img alt="" class="has" height="339" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190829095329397.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70" width="600"></p><p style="text-indent:33px;">网站：<a href="http://www.ypppt.com" rel="nofollow" data-token="dc9dd9dccd5c68814a44e749b18da6b8">http://www.ypppt.com</a></p><h1 id="3%E3%80%81%E5%9B%BE%E7%89%87%E6%93%8D%E4%BD%9C"><a name="t7"></a>3、图片操作</h1><h2 id="3.1%E3%80%81%E5%9B%BE%E7%89%87%E6%97%A0%E9%99%90%E5%8F%98%E5%A4%A7"><a name="t8"></a><strong>3.1、图片无限变大</strong></h2><p style="text-indent:33px;">让你的图片无损放大，放大，再放大！只需要稍稍处理一下就可达到意想不到的效果。</p><p style="text-align:center;"><img alt="" class="has" height="322" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190829095211374.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70" width="600"></p><p style="text-indent:33px;">网站：<a href="http://bigjpg.com/zh" rel="nofollow" data-token="8d703e13460e7b7fdc648da5d508768a">http://bigjpg.com/zh</a></p><h2><a name="t9"></a><strong>3.2、</strong>waifu2x无损放大图片</h2><p style="text-indent:33px;">waifu2x 是一位来自日本的开发者所开源的项目，该项目利用人工智能深度卷积神经网络技术来无损放大图片，堪称是一款图片放大神器。一般图片在放大后可能会出现边界锯齿、线条模糊等问题，而 waifu2x 的算法对此提供了非常好的图片拉伸、降噪、填补机制，使得放大前后的图片给人观感基本一致。</p><p style="text-align:center;"><img alt="" class="has" height="507" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/2019100314550430.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="700"></p><p style="text-indent:33px;">网站：<a href="http://waifu2x.udp.jp/index.zh-CN.html" rel="nofollow" data-token="98f47870e6735c2a1131c95b74b45bc9">http://waifu2x.udp.jp/index.zh-CN.html</a>&nbsp; &nbsp; &nbsp; &nbsp;GitHub源码：<a href="https://github.com/nagadomi/waifu2x" rel="nofollow" data-token="e949642c3a5fdd72c62ae90a8c27499d">https://github.com/nagadomi/waifu2x</a></p><h2><a name="t10"></a><strong>3.3、</strong>Remove Image Background照片抠图和证件照换底色</h2><p style="text-indent:33px;">由 byteq 开发人员 Benjamin Groessing 所开发的 remove.bg 是一款基于 Python、Ruby 和深度学习的抠图工具，它通过 AI 技术自动识别前景层，然后将之与背景层分离开来。网站目前免费开放，无论你是专业设计师还是刚入行的运营小白，都可以上传照片实现自动抠图，免去选择、标记等一系列繁琐的常规操作。真是照片抠图和证件照换底色的绝佳利器。</p><p style="text-align:center;"><img alt="" class="has" height="365" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20191004184717714.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="700"></p><p style="text-indent:33px;">网站：<a href="https://www.remove.bg/" rel="nofollow" data-token="63aa32b42d1f1699ec9def5dd07a8216">https://www.remove.bg/</a>&nbsp; &nbsp; &nbsp;&nbsp;Python代码实现：<a href="https://handsome-man.blog.csdn.net/article/details/102025059" rel="nofollow" data-token="e632d41271e7c6fd1f496a5ab7c8f199">https://handsome-man.blog.csdn.net/article/details/102025059</a></p><h1 id="4%E3%80%81%E6%96%87%E4%BB%B6%E5%85%B1%E4%BA%AB"><a name="t11"></a>4、文件共享</h1><h2 id="4.1%E3%80%81%E6%8B%B7%E8%B4%9D%E5%85%94"><a name="t12"></a>4.1、拷贝兔</h2><p style="text-indent:33px;">拷贝兔是款跨平台文件传输工具，能做到不同设备间文件或文本的临时性迅速分享的应用，支持Windows、Mac、Linux、iOS、Android平台互传；在线使用，用完即走。比百度网盘方便多了。</p><p style="text-align:center;"><img alt="" class="has" height="509" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190829095116687.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70" width="600"></p><p style="text-indent:33px;">网站：<a href="https://cp.anyknew.com" rel="nofollow" data-token="a71ebab3daf3c2ef140b9dd70366e537">https://cp.anyknew.com</a></p><h1 id="5%E3%80%81%E5%BA%94%E5%B1%8A%E7%94%9F%E6%8B%9B%E8%81%98"><a name="t13"></a>5、应届生招聘</h1><h2 id="5.1%E3%80%81%E5%BA%94%E5%B1%8A%E7%94%9F%E6%B1%82%E8%81%8C%E7%BD%91"><a name="t14"></a>5.1、应届生求职网</h2><p style="text-indent:33px;">为大学生提供全方位的求职服务，提供最全、最新、最准确的校园宣讲、全职招聘、兼职实习、知名企业校园招聘、现场招聘会等信息，并且为大学生提供针对性的求职就业指导。</p><p style="text-align:center;"><img alt="" class="has" height="430" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190829095803534.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70" width="600"></p><p style="text-indent:33px;">网站：<a href="http://s.yingjiesheng.com/" rel="nofollow" data-token="857167e6a0fe517f070e2e58cb8d11d9">http://s.yingjiesheng.com/</a></p><h1 id="6%E3%80%81%E7%A8%8B%E5%BA%8F%E5%91%98%E9%9D%A2%E8%AF%95%E9%A2%98%E5%BA%93"><a name="t15"></a>6、程序员面试题库</h1><h2 id="6.1%E3%80%81LeetCode%EF%BC%88%E5%8A%9B%E6%89%A3%EF%BC%89"><a name="t16"></a>6.1、LeetCode（力扣）</h2><p style="text-indent:33px;">力扣题库，提供海量技术面试资源。</p><p style="text-align:center;"><img alt="" class="has" height="341" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190829100245742.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70" width="600"></p><p style="text-indent:33px;">网站：<a href="https://leetcode-cn.com/" rel="nofollow" data-token="84b4a1f4076b54363ac8ef4f79dbcaa9">https://leetcode-cn.com/</a></p><h1 id="7%E3%80%81%E5%8A%9E%E5%85%AC%E3%80%81%E5%BC%80%E5%8F%91%E8%BD%AF%E4%BB%B6"><a name="t17"></a>7、办公、开发软件</h1><h2 id="7.1%E3%80%81%E6%88%91%E7%88%B1%E5%88%86%E4%BA%AB%E7%BD%91"><a name="t18"></a>7.1、我爱分享网</h2><p style="text-indent:33px;">分享各种常用软件安装包（配套破解软件），安装教程和自学视频，让小伙伴即时获取最新的软件，软件无忧，理工科必备利器！</p><p style="text-align:center;"><img alt="" class="has" height="455" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190906124652911.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="700"></p><p style="text-indent:33px;">网站：<a href="http://www.zhanshaoyi.com/rjxz.html" rel="nofollow" data-token="e62e7e93e5fb5130210c377ea07824bc">http://www.zhanshaoyi.com/rjxz.html</a></p><h1 id="8%E3%80%81%E9%AB%98%E6%B8%85%E5%9B%BE%E7%89%87%E3%80%81%E8%A7%86%E9%A2%91%E7%B4%A0%E6%9D%90%E7%BD%91%E7%AB%99%C2%A0"><a name="t19"></a>8、高清图片、视频素材网站&nbsp;</h1><p style="text-indent:33px;">整理了一份实用性爆表的表格图像、视频、矢量……共35个网站，表中含有网站简介和素材类型，做PPT必备啊~</p><p style="text-align:center;"><img alt="" class="has" height="1200" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190907100742907.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="1000"></p><p style="text-indent:33px;">表格下载链接：链接：<a href="https://pan.baidu.com/s/1jPpbkZiqgTJTwcVKh4pd4w" rel="nofollow" data-token="650a7aebeab813646bf05ffeb5e558bf">https://pan.baidu.com/s/1jPpbkZiqgTJTwcVKh4pd4w</a>&nbsp; 提取码：t19j&nbsp;</p><h1 id="9%E3%80%81%E9%A1%B9%E7%9B%AE%E5%BC%80%E6%BA%90"><a name="t20"></a>9、项目开源</h1><h2 id="9.1%E3%80%81GitHub"><a name="t21"></a>9.1、GitHub</h2><p style="text-indent:33px;">GitHub是一个面向开源及私有软件项目的托管平台，因为只支持git 作为唯一的版本库格式进行托管，故名GitHub。</p><p style="text-indent:33px;">作为开源代码库以及版本控制系统，Github拥有超过900万开发者用户。随着越来越多的应用程序转移到了云上，Github已经成为了管理软件开发以及发现已有代码的首选方法。（访问不稳定，经常需要翻墙）</p><p style="text-align:center;"><img alt="" class="has" height="356" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190914145837320.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="700"></p><p style="text-indent:33px;">网站：<a href="https://github.com/" rel="nofollow" data-token="557efaa97b4b6e4b820d679dbd1625ff">https://github.com/</a>&nbsp;</p><h2 id="9.2%E3%80%81%E5%BC%80%E6%BA%90%E4%B8%AD%E5%9B%BD"><a name="t22"></a>9.2、开源中国</h2><p style="text-indent:33px;">开源中国成立于2008年8月，是目前国内最大的开源技术社区，拥有超过200万会员，形成了由开源软件库、代码分享、资讯、协作翻译、码云、众包、招聘等几大模块内容，为IT开发者提供了一个发现、使用、并交流开源技术的平台。</p><p style="text-align:center;"><img alt="" class="has" height="335" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190914145422207.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="700"></p><p style="text-indent:33px;">网站：<a href="https://www.oschina.net/" rel="nofollow" data-token="28b611f932a31d88f6674c96dc118646">https://www.oschina.net/</a>&nbsp;</p><h2 id="9.3%E3%80%81%E7%A0%81%E4%BA%91"><a name="t23"></a>9.3、码云</h2><p style="text-indent:33px;">码云是 OSCHINA.NET 推出的代码托管平台,支持 Git 和 SVN,提供免费的私有仓库托管。目前已有超过 350 万的开发者选择码云。</p><p style="text-align:center;"><img alt="" class="has" height="347" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190914145726985.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="700"></p><p style="text-indent:33px;">网站：<a href="https://gitee.com/" rel="nofollow" data-token="c552c0eb61fbc5bf383ef2cce934b1f7">https://gitee.com/</a>&nbsp;</p><h1 id="10%E3%80%81%E5%9C%A8%E7%BA%BF%E5%B7%A5%E5%85%B7%E5%AE%9D%E5%85%B8%E5%A4%A7%E5%85%A8"><a name="t24"></a>10、在线工具宝典大全</h1><h2 id="10.1%E3%80%81%E7%88%B1%E8%B5%84%E6%96%99%E5%B7%A5%E5%85%B7"><a name="t25"></a>10.1、爱资料工具</h2><p style="text-indent:33px;">爱资料在线工具，为开发运维提供全面的在线工具箱，目前已开发工具270款，包含开发工具、运维工具、常用工具、SEO站长工具等，是好用，方便的在线工具网站。</p><p style="text-align:center;"><img alt="" class="has" height="361" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190914221056195.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="700"></p><p style="text-indent:33px;">网站：<a href="https://www.toolnb.com/" rel="nofollow" data-token="554f265b58597dada0be2c2bcca524f0">https://www.toolnb.com/</a>&nbsp;</p><h2 id="10.2%E3%80%81%E8%8F%9C%E9%B8%9F%E5%B7%A5%E5%85%B7"><a name="t26"></a>10.2、菜鸟工具</h2><p style="text-indent:33px;">最大的特点是支持各种语言的在线编辑，可以在网页上运行代码。</p><p style="text-align:center;"><img alt="" class="has" height="427" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190927205931850.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9oYW5kc29tZS1tYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="700"></p><p style="text-indent:33px;">网站：<a href="https://c.runoob.com/" rel="nofollow" data-token="6daa6578e924c080b144a574d55b28f1">https://c.runoob.com/</a>&nbsp;</p>                                    </div>                                    ]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sublime弹出更新框解决方案</title>
      <link href="ide/sublime/sublime-license/"/>
      <url>ide/sublime/sublime-license/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>很多新手朋友使用sublime,它是一个开源免费和轻量级的编辑器</p><p>但是在使用的过程中,它总是会弹出提示你激活或者更新版本的弹出框,每次都要点击关闭它</p><p>今天小编就教大家如何去掉这个弹框</p><h3 id="license的配置"><a href="#license的配置" class="headerlink" title="license的配置"></a>license的配置</h3><p>首先,直接就打开软件&gt;</p><p>在help选项卡中,选择Enter license</p><p>输入下面的激活码</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">ZYNGA INC.</span><br><span class="line">50 User License</span><br><span class="line">EA7E-811825</span><br><span class="line">927BA117 84C9300F 4A0CCBC4 34A56B44</span><br><span class="line">985E4562 59F2B63B CCCFF92F 0E646B83</span><br><span class="line">0FD6487D 1507AE29 9CC4F9F5 0A6F32E3</span><br><span class="line">0343D868 C18E2CD5 27641A71 25475648</span><br><span class="line">309705B3 E468DDC4 1B766A18 7952D28C</span><br><span class="line">E627DDBA 960A2153 69A2D98A C87C0607</span><br><span class="line">45DC6049 8C04EC29 D18DFA40 442C680B</span><br><span class="line">1342224D 44D90641 33A3B9F2 46AADB8F</span><br></pre></td></tr></table></figure><p>sublimetext3会提示license版本不对,点击取消即可</p><h3 id="配置设置"><a href="#配置设置" class="headerlink" title="配置设置"></a>配置设置</h3><p>在设置文件中加入下面一行,来关闭检查更新</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&quot;update_check&quot;:false,</span><br></pre></td></tr></table></figure><p>更多关于sublime的快捷设置和快捷键可以参考:<a href="https://victorfengming.gitee.io/blog/sublime-keybings-settings/">sublime快捷键和设置配置(jetbrains习惯)</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> sublime </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中final关键字的几种用法</title>
      <link href="java/javaold/java-final/"/>
      <url>java/javaold/java-final/</url>
      
        <content type="html"><![CDATA[<div class="post">      <div class="clear"></div>  <div class="postBody">    <div id="cnblogs_post_body" class="blogpost-body ">    <p>在java的关键字中，<strong>static</strong>和<strong>final</strong>是两个我们必须掌握的关键字。不同于其他关键字，他们都有多种用法，而且在一定环境下使用，可以提高程序的运行性能，优化程序的结构。下面我们来了解一下<strong>final</strong>关键字及其用法。</p><h2>final关键字</h2><p>在java中，final的含义在不同的场景下有细微的差别，但总体上来说，它指的是“<strong>这是不可变的</strong>”。下面，我们来讲final的四种主要用法。</p><h3>1.修饰数据</h3><p>在编写程序时，我们经常需要说明一个数据是不可变的，我们成为常量。在java中，用final关键字修饰的变量，只能进行一次赋值操作，并且在生存期内不可以改变它的值。更重要的是，final会告诉编译器，这个数据是不会修改的，那么编译器就可能会在编译时期就对该数据进行替换甚至执行计算，这样可以对我们的程序起到一点优化。不过在针对基本类型和引用类型时，final关键字的效果存在细微差别。我们来看下面的例子：</p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div><pre><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Value {</span><span style="color: #008080;"> 2</span>     <span style="color: #0000ff;">int</span><span style="color: #000000;"> v;</span><span style="color: #008080;"> 3</span>     <span style="color: #0000ff;">public</span> Value(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {</span><span style="color: #008080;"> 4</span>         <span style="color: #0000ff;">this</span>.v =<span style="color: #000000;"> v;</span><span style="color: #008080;"> 5</span> <span style="color: #000000;">    }</span><span style="color: #008080;"> 6</span> <span style="color: #000000;">}</span><span style="color: #008080;"> 7</span> <span style="color: #008080;"> 8</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> FinalTest {</span><span style="color: #008080;"> 9</span>     <span style="color: #008080;">10</span>     <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">int</span> f1 = 1<span style="color: #000000;">;</span><span style="color: #008080;">11</span>     <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> f2;</span><span style="color: #008080;">12</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> FinalTest() {</span><span style="color: #008080;">13</span>         f2 = 2<span style="color: #000000;">;</span><span style="color: #008080;">14</span> <span style="color: #000000;">    }</span><span style="color: #008080;">15</span> <span style="color: #008080;">16</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {</span><span style="color: #008080;">17</span>         <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">int</span> value1 = 1<span style="color: #000000;">;</span><span style="color: #008080;">18</span>         <span style="color: #008000;">//</span><span style="color: #008000;"> value1 = 4;</span><span style="color: #008080;">19</span>         <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">double</span><span style="color: #000000;"> value2;</span><span style="color: #008080;">20</span>         value2 = 2.0<span style="color: #000000;">;</span><span style="color: #008080;">21</span>         <span style="color: #0000ff;">final</span> Value value3 = <span style="color: #0000ff;">new</span> Value(1<span style="color: #000000;">);</span><span style="color: #008080;">22</span>         value3.v = 4<span style="color: #000000;">;</span><span style="color: #008080;">23</span> <span style="color: #000000;">    }</span><span style="color: #008080;">24</span> }</pre><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div></div><p>上面的例子中，我们先来看一下main方法中的几个final修饰的数据，在给value1赋初始值之后，我们无法再对value1的值进行修改，final关键字起到了常量的作用。从value2我们可以看到，final修饰的变量可以不在声明时赋值，即可以先声明，后赋值。value3时一个引用变量，这里我们可以看到final修饰引用变量时，只是限定了引用变量的引用不可改变，即不能将value3再次引用另一个Value对象，但是引用的对象的值是可以改变的，从内存模型中我们看的更加清晰：</p><p><img src= "/img/loading.gif" data-lazy-src="https://images2015.cnblogs.com/blog/1055692/201701/1055692-20170130101552386-541665575.jpg" alt=""></p><p>上图中，final修饰的值用粗线条的边框表示它的值是不可改变的，我们知道引用变量的值实际上是它所引用的对象的地址，也就是说该地址的值是不可改变的，从而说明了为什么引用变量不可以改变引用对象。而实际引用的对象实际上是不受final关键字的影响的，所以它的值是可以改变的。</p><p>另一方面，我们看到了用final修饰成员变量时的细微差别，因为final修饰的数据的值是不可改变的，所以我们必须确保在使用前就已经对成员变量赋值了。因此对于final修饰的成员变量，我们有且只有两个地方可以给它赋值，一个是声明该成员时赋值，另一个是在构造方法中赋值，在这两个地方我们必须给它们赋初始值。</p><p>最后我们需要注意的一点是，同时使用static和final修饰的成员在内存中只占据一段不能改变的存储空间。</p><h3>2.修饰方法参数</h3><p>前面我们可以看到，如果变量是我们自己创建的，那么使用final修饰表示我们只会给它赋值一次且不会改变变量的值。那么如果变量是作为参数传入的，我们怎么保证它的值不会改变呢？这就用到了final的第二种用法，即在我们编写方法时，可以在参数前面添加final关键字，它表示在整个方法中，我们不会（实际上是不能）改变参数的值：</p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div><pre><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> FinalTest {<pre><code>&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;/*&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt; ... &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;*/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; finalFunc(&lt;span style=&quot;color: #0000ff;&quot;&gt;final&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; i, &lt;span style=&quot;color: #0000ff;&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Value value) &#123;    &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt; i = 5; 不能改变i的值    &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt; v = new Value(); 不能改变v的值&lt;/span&gt;    value.v = 5; &lt;span style=&quot;color: #008000;&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt; 可以改变引用对象的值&lt;/span&gt;</code></pre><p><span style="color: #000000;">    }<br>}</span></pre></p><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div></div><h3>3.修饰方法</h3><p>第三种方式，即用final关键字修饰方法，它表示该方法不能被覆盖。这种使用方式主要是从设计的角度考虑，即明确告诉其他可能会继承该类的程序员，不希望他们去覆盖这个方法。这种方式我们很容易理解，然而，关于private和final关键字还有一点联系，这就是类中所有的private方法都隐式地指定为是final的，由于无法在类外使用private方法，所以也就无法覆盖它。</p><h3>4.修饰类</h3><p>了解了final关键字的其他用法，我们很容易可以想到使用final关键字修饰类的作用，那就是用final修饰的类是无法被继承的。</p><p>上面我们讲解了final的四种用法，然而，对于第三种和第四种用法，我们却甚少使用。这不是没有道理的，从final的设计来讲，这两种用法甚至可以说是鸡肋，因为对于开发人员来讲，如果我们写的类被继承的越多，就说明我们写的类越有价值，越成功。即使是从设计的角度来讲，也没有必要将一个类设计为不可继承的。Java标准库就是一个很好的反例，特别是Java 1.0/1.1中Vector类被如此广泛的运用，如果所有的方法均未被指定为final的话，它可能会更加有用。如此有用的类，我们很容易想到去继承和重写他们，然而，由于final的作用，导致我们对Vector类的扩展受到了一些阻碍，导致了Vector并没有完全发挥它应有的全部价值。</p><h2>总结</h2><p>final关键字是我们经常使用的关键字之一，它的用法有很多，但是并不是每一种用法都值得我们去广泛使用。它的主要用法有以下四种：</p><ol><li>用来修饰数据，包括成员变量和局部变量，该变量只能被赋值一次且它的值无法被改变。对于成员变量来讲，我们必须在声明时或者构造方法中对它赋值；</li><li>用来修饰方法参数，表示在变量的生存期中它的值不能被改变；</li><li>修饰方法，表示该方法无法被重写；</li><li>修饰类，表示该类无法被继承。</li></ol><p>上面的四种方法中，第三种和第四种方法需要谨慎使用，因为在大多数情况下，如果是仅仅为了一点设计上的考虑，我们并不需要使用final来修饰方法和类。</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中的继承</title>
      <link href="java/javaold/java-inherit/"/>
      <url>java/javaold/java-inherit/</url>
      
        <content type="html"><![CDATA[<h3 id="Java-继承"><a href="#Java-继承" class="headerlink" title="Java 继承"></a>Java 继承</h3><p>继承是java面向对象编程技术的一块基石，因为它允许创建分等级层次的类。继承可以理解为一个对象从另一个对象获取属性的过程。</p><p>如果类A是类B的父类，而类B是类C的父类，我们也称C是A的子类，类C是从类A继承而来的。在Java中，类的继承是单一继承，也就是说，一个子类只能拥有一个父类</p><p>继承中最常使用的两个关键字是extends和implements。</p><p>这两个关键字的使用决定了一个对象和另一个对象是否是IS-A(是一个)关系。</p><p>通过使用这两个关键字，我们能实现一个对象获取另一个对象的属性。</p><p>所有Java的类均是由java.lang.Object类继承而来的，所以Object是所有类的祖先类，而除了Object外，所有类必须有一个父类。</p><p>通过过extends关键字可以申明一个类是继承另外一个类而来的，一般形式如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// A.java</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> i;</span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">int</span> j;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">func</span><span class="params">()</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">// B.java</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>以上的代码片段说明，B由A继承而来的，B是A的子类。而A是Object的子类，这里可以不显示地声明。</p><p>作为子类，B的实例拥有A所有的成员变量，但对于private的成员变量B却没有访问权限，这保障了A的封装性。</p><h3 id="IS-A关系"><a href="#IS-A关系" class="headerlink" title="IS-A关系"></a>IS-A关系</h3><p>IS-A就是说:一个对象是另一个对象的一个分类。</p><p>下面是使用关键字extends实现继承。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Animal</span></span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Mammal</span> <span class="keyword">extends</span> <span class="title">Animal</span></span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Reptile</span> <span class="keyword">extends</span> <span class="title">Animal</span></span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">extends</span> <span class="title">Mammal</span></span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>基于上面的例子，以下说法是正确的：</p><ul><li><p>Animal类是Mammal类的父类。</p></li><li><p>Animal类是Reptile类的父类。</p></li><li><p>Mammal类和Reptile类是Animal类的子类。</p></li><li><p>Dog类既是Mammal类的子类又是Animal类的子类。<br>分析以上示例中的IS-A关系，如下：</p></li><li><p>Mammal IS-A Animal</p></li><li><p>Reptile IS-A Animal</p></li><li><p>Dog IS-A Mammal<br>因此 : Dog IS-A Animal</p></li></ul><p>通过使用关键字extends，子类可以继承父类的除private属性外所有的属性。</p><p>我们通过使用instanceof 操作符，能够确定Mammal IS-A Animal</p><h5 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">extends</span> <span class="title">Mammal</span></span>&#123;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String args[])</span></span>&#123;</span><br><span class="line"></span><br><span class="line">      Animal a = <span class="keyword">new</span> Animal();</span><br><span class="line">      Mammal m = <span class="keyword">new</span> Mammal();</span><br><span class="line">      Dog d = <span class="keyword">new</span> Dog();</span><br><span class="line"></span><br><span class="line">      System.out.println(m <span class="keyword">instanceof</span> Animal);</span><br><span class="line">      System.out.println(d <span class="keyword">instanceof</span> Mammal);</span><br><span class="line">      System.out.println(d <span class="keyword">instanceof</span> Animal);</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>以上实例编译运行结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">true</span><br><span class="line">true</span><br><span class="line">true</span><br></pre></td></tr></table></figure><p>介绍完extends关键字之后，我们再来看下implements关键字是怎样使用来表示IS-A关系。</p><p>Implements关键字使用在类继承接口的情况下， 这种情况不能使用关键字extends。</p><h5 id="实例-1"><a href="#实例-1" class="headerlink" title="实例"></a>实例</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Animal</span> </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Mammal</span> <span class="keyword">implements</span> <span class="title">Animal</span></span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">extends</span> <span class="title">Mammal</span></span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>instanceof 关键字<br>可以使用 instanceof 运算符来检验Mammal和dog对象是否是Animal类的一个实例。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Animal</span></span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mammal</span> <span class="keyword">implements</span> <span class="title">Animal</span></span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">extends</span> <span class="title">Mammal</span></span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String args[])</span></span>&#123;</span><br><span class="line"></span><br><span class="line">      Mammal m = <span class="keyword">new</span> Mammal();</span><br><span class="line">      Dog d = <span class="keyword">new</span> Dog();</span><br><span class="line"></span><br><span class="line">      System.out.println(m <span class="keyword">instanceof</span> Animal);</span><br><span class="line">      System.out.println(d <span class="keyword">instanceof</span> Mammal);</span><br><span class="line">      System.out.println(d <span class="keyword">instanceof</span> Animal);</span><br><span class="line">   &#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>以上实例编译运行结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">true</span><br><span class="line">true</span><br><span class="line">true</span><br></pre></td></tr></table></figure><h3 id="HAS-A-关系"><a href="#HAS-A-关系" class="headerlink" title="HAS-A 关系"></a>HAS-A 关系</h3><p>HAS-A代表类和它的成员之间的从属关系。这有助于代码的重用和减少代码的错误。</p><h5 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Vehicle</span></span>&#123;&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Speed</span></span>&#123;&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Van</span> <span class="keyword">extends</span> <span class="title">Vehicle</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Speed sp;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>Van类和Speed类是HAS-A关系(Van有一个Speed)，这样就不用将Speed类的全部代码粘贴到Van类中了，并且Speed类也可以重复利用于多个应用程序。</p><p>在面向对象特性中，用户不必担心类的内部怎样实现。</p><p>Van类将实现的细节对用户隐藏起来，因此，用户只需要知道怎样调用Van类来完成某一功能，而不必知道Van类是自己来做还是调用其他类来做这些工作。</p><p>Java只支持单继承，也就是说，一个类不能继承多个类。</p><p>下面的做法是不合法的：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="keyword">extends</span> <span class="title">Animal</span>, <span class="title">Mammal</span></span>&#123;&#125; </span><br></pre></td></tr></table></figure><p>Java只支持单继承（继承基本类和抽象类），但是我们可以用接口来实现（多继承接口来实现）,脚本结构如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Apple</span> <span class="keyword">extends</span> <span class="title">Fruit</span> <span class="keyword">implements</span> <span class="title">Fruit1</span>, <span class="title">Fruit2</span></span>&#123;&#125;</span><br></pre></td></tr></table></figure><p>一般我们继承基本类和抽象类用extends关键字，实现接口类的继承用implements关键字。</p>]]></content>
      
      
      
        <tags>
            
            <tag> oop </tag>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 重写(Override)与重载(Overload)</title>
      <link href="java/javaold/java-override-overload/"/>
      <url>java/javaold/java-override-overload/</url>
      
        <content type="html"><![CDATA[<div class="content-intro view-box "> <hr> <h3>重写(Override)</h3> <p> 重写是子类对父类的允许访问的方法的实现过程进行重新编写！返回值和形参都不能改变。即外壳不变，核心重写！ </p> <p>重写的好处在于子类可以根据需要，定义特定于自己的行为。</p><p> 也就是说子类能够根据需要实现父类的方法。</p><p> 在面向对象原则里，重写意味着可以重写任何现有方法。实例如下：</p> <pre lang="java"><code class="java hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span></span>&#123;<p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">move</span><span class="hljs-params">()</span></span>&#123;<br>      System.out.println(<span class="hljs-string">“动物可以移动”</span>);<br>   &#125;<br>&#125;</p><p><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span></span>&#123;</p><p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">move</span><span class="hljs-params">()</span></span>&#123;<br>      System.out.println(<span class="hljs-string">“狗可以跑和走”</span>);<br>   &#125;<br>&#125;</p><p><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestDog</span></span>&#123;</p><p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String args[])</span></span>&#123;<br>      Animal a = <span class="hljs-keyword">new</span> Animal(); <span class="hljs-comment">// Animal 对象</span><br>      Animal b = <span class="hljs-keyword">new</span> Dog(); <span class="hljs-comment">// Dog 对象</span></p><pre><code>  a.move();&lt;span class=&quot;hljs-comment&quot;&gt;// 执行 Animal 类的方法&lt;/span&gt;  b.move();&lt;span class=&quot;hljs-comment&quot;&gt;//执行 Dog 类的方法&lt;/span&gt;</code></pre><p>   }<br>}<br></code></pre> <p>以上实例编译运行结果如下：</p> <pre lang="java"><code class="java hljs">动物可以移动<br>狗可以跑和走<br></code></pre> <p>在上面的例子中可以看到，尽管b属于Animal类型，但是它运行的是Dog类的move方法。</p><p> 这是由于在编译阶段，只是检查参数的引用类型。</p><p> 然而在运行时，Java虚拟机(JVM)指定对象的类型并且运行该对象的方法。</p><p> 因此在上面的例子中，之所以能编译成功，是因为Animal类中存在move方法，然而运行时，运行的是特定对象的方法。</p><p> 思考以下例子：</p> <pre lang="java"><code class="java hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span></span>&#123;</p><p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">move</span><span class="hljs-params">()</span></span>&#123;<br>      System.out.println(<span class="hljs-string">“动物可以移动”</span>);<br>   &#125;<br>&#125;</p><p><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span></span>&#123;</p><p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">move</span><span class="hljs-params">()</span></span>&#123;<br>      System.out.println(<span class="hljs-string">“狗可以跑和走”</span>);<br>   &#125;<br>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span></span>&#123;<br>      System.out.println(<span class="hljs-string">“狗可以吠叫”</span>);<br>   &#125;<br>&#125;</p><p><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestDog</span></span>&#123;</p><p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String args[])</span></span>&#123;<br>      Animal a = <span class="hljs-keyword">new</span> Animal(); <span class="hljs-comment">// Animal 对象</span><br>      Animal b = <span class="hljs-keyword">new</span> Dog(); <span class="hljs-comment">// Dog 对象</span></p><pre><code>  a.move();&lt;span class=&quot;hljs-comment&quot;&gt;// 执行 Animal 类的方法&lt;/span&gt;  b.move();&lt;span class=&quot;hljs-comment&quot;&gt;//执行 Dog 类的方法&lt;/span&gt;  a.bark();&lt;span class=&quot;hljs-comment&quot;&gt;//执行 Animal 类的方法&lt;/span&gt;</code></pre><p>   }<br>}<br></code></pre><p>以上实例编译运行结果如下：</p> <pre lang="java"><code class="java hljs">TestDog.java:<span class="hljs-number">30</span>: cannot find symbol<br>symbol  : <span class="hljs-function">method <span class="hljs-title">bark</span><span class="hljs-params">()</span><br>location: class Animal<br>                a.<span class="hljs-title">bark</span><span class="hljs-params">()</span></span>;<br>                 ^<br></code></pre> <p>该程序将抛出一个编译错误，因为a的引用类型Animal没有bark方法。</p> <hr> <h3>方法重写的规则</h3> <ul> <li> 参数列表必须完全与被重写方法的相同；</li> <li> 返回类型必须完全与被重写方法的返回类型相同；</li> <li>子类方法的访问权限必须大于或等于父类方法的访问权限。例如：如果父类的一个方法被声明为public，那么在子类中重写该方法就不能声明为protected。</li> <li> 父类的成员方法只能被它的子类重写。</li> <li> 声明为final的方法不能被重写。</li> <li> 声明为static的方法不能被重写，但是能够被再次声明。</li> <li> 子类和父类在同一个包中，那么子类可以重写父类所有方法，除了声明为private和final的方法。</li> <li> 子类和父类不在同一个包中，那么子类只能够重写父类的声明为public和protected的非final方法。</li> <li> 重写的方法能够抛出任何非强制异常，无论被重写的方法是否抛出异常。但是，重写的方法不能抛出新的强制性异常，或者比被重写方法声明的更广泛的强制性异常，反之则可以。</li> <li> 构造方法不能被重写。</li> <li>如果不能继承一个方法，则不能重写这个方法。</li> </ul> <hr><h3>Super关键字的使用</h3> <p> 当需要在子类中调用父类的被重写方法时，要使用super关键字。 </p> <pre lang="java"><code class="java hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span></span>&#123;</p><p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">move</span><span class="hljs-params">()</span></span>&#123;<br>      System.out.println(<span class="hljs-string">“动物可以移动”</span>);<br>   &#125;<br>&#125;</p><p><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span></span>&#123;</p><p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">move</span><span class="hljs-params">()</span></span>&#123;<br>      <span class="hljs-keyword">super</span>.move(); <span class="hljs-comment">// 应用super类的方法</span><br>      System.out.println(<span class="hljs-string">“狗可以跑和走”</span>);<br>   &#125;<br>&#125;</p><p><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestDog</span></span>&#123;</p><p>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String args[])</span></span>&#123;</p><pre><code>  Animal b = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Dog(); &lt;span class=&quot;hljs-comment&quot;&gt;//&lt;/span&gt;  b.move(); &lt;span class=&quot;hljs-comment&quot;&gt;//执行 Dog类的方法&lt;/span&gt;</code></pre><p>   }<br>}<br></code></pre><p>以上实例编译运行结果如下：</p> <pre lang="java"><code class="java hljs">动物可以移动<br>狗可以跑和走<br></code></pre>  <h3>重载(Overload)</h3> <p>重载(overloading) 是在一个类里面，方法名字相同，而参数不同。返回类型呢？可以相同也可以不同。</p> <p>每个重载的方法（或者构造函数）都必须有一个独一无二的参数类型列表。</p> <p>只能重载构造函数</p> <p>重载规则</p> <ul> <li>被重载的方法必须改变参数列表；</li> <li>被重载的方法可以改变返回类型；</li> <li>被重载的方法可以改变访问修饰符；</li> <li>被重载的方法可以声明新的或更广的检查异常；</li> <li>方法能够在同一个类中或者在一个子类中被重载。</li> </ul> <h3>实例</h3> <pre lang="java"><code class="java hljs"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Overloading</span> </span>&#123;</p><p>  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">test</span><span class="hljs-params">()</span></span>&#123;<br>    System.out.println(<span class="hljs-string">“test1”</span>);<br>    <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;<br>  &#125;</p><p>  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">test</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a)</span></span>&#123;<br>    System.out.println(<span class="hljs-string">“test2”</span>);<br>  &#125; </p><p>  <span class="hljs-comment">//以下两个参数类型顺序不同</span><br>  <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">test</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a,String s)</span></span>&#123;<br>    System.out.println(<span class="hljs-string">“test3”</span>);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">“returntest3”</span>;<br>  &#125; </p><p>  <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">test</span><span class="hljs-params">(String s,<span class="hljs-keyword">int</span> a)</span></span>&#123;<br>    System.out.println(<span class="hljs-string">“test4”</span>);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">“returntest4”</span>;<br>  &#125; </p><p>  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span></span>&#123;<br>    Overloading o = <span class="hljs-keyword">new</span> Overloading();<br>    System.out.println(o.test());<br>    o.test(<span class="hljs-number">1</span>);<br>    System.out.println(o.test(<span class="hljs-number">1</span>,<span class="hljs-string">“test3”</span>));<br>    System.out.println(o.test(<span class="hljs-string">“test4”</span>,<span class="hljs-number">1</span>));<br>  &#125;<br></code></pre> <hr><h3>重写与重载之间的区别</h3> <table class="reference   "> <tbody> <tr> <th width="72">区别点</th> <th width="80">重载方法</th> <th width="340">重写方法</th> </tr> <tr> <td width="72">参数列表</td> <td width="80">必须修改</td> <td width="340">一定不能修改</td> </tr> <tr> <td width="72">返回类型</td> <td width="80">可以修改</td> <td width="340">一定不能修改</td> </tr> <tr> <td width="72">异常</td> <td width="80">可以修改</td> <td width="340">可以减少或删除，一定不能抛出新的或者更广的异常</td> </tr> <tr> <td width="72">访问</td> <td width="80">可以修改</td> <td width="340">一定不能做更严格的限制（可以降低限制）</td> </tr> </tbody> </table><p><br></p></div></p>]]></content>
      
      
      
        <tags>
            
            <tag> oop </tag>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java中的多态</title>
      <link href="java/javaold/java-polymorphism/"/>
      <url>java/javaold/java-polymorphism/</url>
      
        <content type="html"><![CDATA[<div class="content-intro view-box "><h3>Java 多态</h3> <hr> <p>多态是同一个行为具有多个不同表现形式或形态的能力。 </p> <p>多态性是对象多种表现形式的体现。</p> <p> 比如我们说"宠物"这个对象，它就有很多不同的表达或实现，比如有小猫、小狗、蜥蜴等等。那么我到宠物店说"请给我一只宠物"，服务员给我小猫、小狗或者蜥蜴都可以，我们就说"宠物"这个对象就具备多态性。 </p> <p>接下来让我们通过实例来了解Java的多态。</p> <h4>例子</h4> <pre lang="java"><code class="java hljs"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Vegetarian</span></span>&#123;&#125;<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span></span>&#123;&#125;<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Deer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Vegetarian</span></span>&#123;&#125;</code></pre> <p> 因为Deer类具有多重继承，所以它具有多态性。以上实例解析如下： </p> <ul> <li> 一个 Deer IS-A（是一个） Animal</li> <li> 一个 Deer IS-A（是一个） Vegetarian</li> <li> 一个 Deer IS-A（是一个） Deer</li> <li> 一个 Deer IS-A（是一个）Object</li> </ul> <p>在Java中，所有的对象都具有多态性，因为任何对象都能通过IS-A测试的类型和Object类。</p><p> 访问一个对象的唯一方法就是通过引用型变量。</p><p> 引用型变量只能有一种类型，一旦被声明，引用型变量的类型就不能被改变了。</p><p> 引用型变量不仅能够被重置为其他对象，前提是这些对象没有被声明为final。还可以引用和它类型相同的或者相兼容的对象。它可以声明为类类型或者接口类型。</p> <p>当我们将引用型变量应用于Deer对象的引用时，下面的声明是合法的： </p> <pre lang="java"><code class="java hljs">Deer d = <span class="hljs-keyword">new</span> Deer();Animal a = d;Vegetarian v = d;Object o = d;</code></pre> <p>所有的引用型变量d,a,v,o都指向堆中相同的Deer对象。</p> <hr> <h3>虚方法</h3> <p>我们将介绍在Java中，当设计类时，被重写的方法的行为怎样影响多态性。</p><p> 我们已经讨论了方法的重写，也就是子类能够重写父类的方法。</p><p> 当子类对象调用重写的方法时，调用的是子类的方法，而不是父类中被重写的方法。</p><p> 要想调用父类中被重写的方法，则必须使用关键字super。</p> <pre lang="java"><code class="java hljs"><span class="hljs-comment">/* 文件名 : Employee.java */</span><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span></span>&#123;   <span class="hljs-keyword">private</span> String name;   <span class="hljs-keyword">private</span> String address;   <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> number;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Employee</span><span class="hljs-params">(String name, String address, <span class="hljs-keyword">int</span> number)</span>   </span>&#123;      System.out.println(<span class="hljs-string">"Constructing an Employee"</span>);      <span class="hljs-keyword">this</span>.name = name;      <span class="hljs-keyword">this</span>.address = address;      <span class="hljs-keyword">this</span>.number = number;   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">mailCheck</span><span class="hljs-params">()</span>   </span>&#123;      System.out.println(<span class="hljs-string">"Mailing a check to "</span> + <span class="hljs-keyword">this</span>.name       + <span class="hljs-string">" "</span> + <span class="hljs-keyword">this</span>.address);   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span>   </span>&#123;      <span class="hljs-keyword">return</span> name + <span class="hljs-string">" "</span> + address + <span class="hljs-string">" "</span> + number;   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span>   </span>&#123;      <span class="hljs-keyword">return</span> name;   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getAddress</span><span class="hljs-params">()</span>   </span>&#123;      <span class="hljs-keyword">return</span> address;   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAddress</span><span class="hljs-params">(String newAddress)</span>   </span>&#123;      address = newAddress;   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getNumber</span><span class="hljs-params">()</span>   </span>&#123;     <span class="hljs-keyword">return</span> number;   &#125;&#125;</code></pre> <p>假设下面的类继承Employee类：</p> <pre lang="java"><code class="java hljs"><span class="hljs-comment">/* 文件名 : Salary.java */</span><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Salary</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Employee</span></span>&#123;   <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> salary; <span class="hljs-comment">//Annual salary</span>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Salary</span><span class="hljs-params">(String name, String address, <span class="hljs-keyword">int</span> number, <span class="hljs-keyword">double</span>      salary)</span>   </span>&#123;       <span class="hljs-keyword">super</span>(name, address, number);       setSalary(salary);   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">mailCheck</span><span class="hljs-params">()</span>   </span>&#123;       System.out.println(<span class="hljs-string">"Within mailCheck of Salary class "</span>);       System.out.println(<span class="hljs-string">"Mailing check to "</span> + getName()       + <span class="hljs-string">" with salary "</span> + salary);   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getSalary</span><span class="hljs-params">()</span>   </span>&#123;       <span class="hljs-keyword">return</span> salary;   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSalary</span><span class="hljs-params">(<span class="hljs-keyword">double</span> newSalary)</span>   </span>&#123;       <span class="hljs-keyword">if</span>(newSalary &gt;= <span class="hljs-number">0.0</span>)       &#123;          salary = newSalary;       &#125;   &#125;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">computePay</span><span class="hljs-params">()</span>   </span>&#123;      System.out.println(<span class="hljs-string">"Computing salary pay for "</span> + getName());      <span class="hljs-keyword">return</span> salary/<span class="hljs-number">52</span>;   &#125;&#125;</code></pre> <p>现在我们仔细阅读下面的代码，尝试给出它的输出结果：</p> <pre lang="java"><code class="java hljs"><span class="hljs-comment">/* 文件名 : VirtualDemo.java */</span><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VirtualDemo</span></span>&#123;   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String [] args)</span>   </span>&#123;      Salary s = <span class="hljs-keyword">new</span> Salary(<span class="hljs-string">"Mohd Mohtashim"</span>, <span class="hljs-string">"Ambehta, UP"</span>, <span class="hljs-number">3</span>, <span class="hljs-number">3600.00</span>);      Employee e = <span class="hljs-keyword">new</span> Salary(<span class="hljs-string">"John Adams"</span>, <span class="hljs-string">"Boston, MA"</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2400.00</span>);      System.out.println(<span class="hljs-string">"Call mailCheck using Salary reference --"</span>);      s.mailCheck();      System.out.println(<span class="hljs-string">"\n Call mailCheck using Employee reference--"</span>);      e.mailCheck();    &#125;&#125;</code></pre> <p>以上实例编译运行结果如下：</p> <pre lang="java"><code class="java hljs">Constructing an EmployeeConstructing an EmployeeCall mailCheck using Salary reference --Within mailCheck of Salary <span class="hljs-class"><span class="hljs-keyword">class</span><span class="hljs-title">Mailing</span> <span class="hljs-title">check</span> <span class="hljs-title">to</span> <span class="hljs-title">Mohd</span> <span class="hljs-title">Mohtashim</span> <span class="hljs-title">with</span> <span class="hljs-title">salary</span> 3600.0<p><span class="hljs-title">Call</span> <span class="hljs-title">mailCheck</span> <span class="hljs-title">using</span> <span class="hljs-title">Employee</span> <span class="hljs-title">reference</span>–<br><span class="hljs-title">Within</span> <span class="hljs-title">mailCheck</span> <span class="hljs-title">of</span> <span class="hljs-title">Salary</span> <span class="hljs-title">class</span><br><span class="hljs-title">Mailing</span> <span class="hljs-title">check</span> <span class="hljs-title">to</span> <span class="hljs-title">John</span> <span class="hljs-title">Adams</span> <span class="hljs-title">with</span> <span class="hljs-title">salary</span> 2400.0<br></span></code></pre> <p>例子中，我们实例化了两个Salary对象。一个使用Salary引用s，另一个使用Employee引用。</p><p> 编译时，编译器检查到mailCheck()方法在Salary类中的声明。</p><p> 在调用s.mailCheck()时，Java虚拟机(JVM)调用Salary类的mailCheck()方法。</p><p> 因为e是Employee的引用，所以调用e的mailCheck()方法则有完全不同的结果。</p><p> 当编译器检查e.mailCheck()方法时，编译器检查到Employee类中的mailCheck()方法。</p><p> 在编译的时候，编译器使用Employee类中的mailCheck()方法验证该语句， 但是在运行的时候，Java虚拟机(JVM)调用的是Salary类中的mailCheck()方法。</p><p> 该行为被称为虚拟方法调用，该方法被称为虚拟方法。</p><p> Java中所有的方法都能以这种方式表现，借此，重写的方法能在运行时调用，不管编译的时候源代码中引用变量是什么数据类型。</p></div></p>]]></content>
      
      
      
        <tags>
            
            <tag> oop </tag>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PHP中的输出语句对比</title>
      <link href="php/php-output/"/>
      <url>php/php-output/</url>
      
        <content type="html"><![CDATA[<p>通过前面的学习了解了php的基本语法，今天向大家简单介绍php的几种输出方式：</p><ol><li>  echo 常用的输出语句，例如：echo ‘helloworld！’;</li><li>  print() 输出语句，有返回值。例如：print(‘helloworld！’); 输出成功返回1，失败返回0。</li><li>  printf(); 格式化输出字符串。例如：printf(“%d,%f”,12,12.3);</li><li>  print_r(); 输出数组、对象等复合数据类型。例如：print_r($array);</li><li> var_dump(); 可以判断一个变量的类型与长度,并输出变量的数值。例如：var_dump(‘helloworld！’);</li><li> sprintf 函数也用做字符串格式化。例如： $formatted = sprintf ( “%01.2f “, ‘123.1’ ) ;  </li></ol><p>为方便我们的记忆，先对这几种不同的输出方式做个对比。</p><ul><li>echo   - 可以输出一个或多个字符串</li><li>print   - 只能输出简单类型变量的值,如int,string</li><li>print_r - 可以输出复杂类型变量的值,如数组,对象</li><li>printf -函数用于格式化输出字符串，主要用于字符串中以%开头的格式字符串替换。</li><li>sprintf -函数也用做字符串格式化。该函数与 printf 函数基本相同， 但它可以将转换后的结果保存到一个字符串变量中，而不是直接输出。(因为跟printf类似，下面就不做详细演示了)</li><li>var_dump -打印变量的相关信息,包括表达式的类型与值,通过缩进显示其结构。</li></ul><p><strong>提示</strong>：echo输出的速度比print快,echo是PHP语句,没有返回值,print和print_r是PHP函数,函数有返回值。</p><p>print返回值为1(int类型),print_r返回值为true(bool类型)。</p><h3 id="echo"><a href="#echo" class="headerlink" title="echo"></a>echo</h3><p>echo 是一个语言结构，使用的时候可以不用加括号，也可以加上括号： echo 或 echo()。</p><h5 id="显示字符串"><a href="#显示字符串" class="headerlink" title="显示字符串"></a>显示字符串</h5><p>下面的实例演示了如何使用 echo 命令输出字符串（字符串可以包含 HTML 标签）：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;&lt;h2&gt;PHP is fun!&lt;/h2&gt;&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;Hello world!&lt;br&gt;&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;I&#x27;m about to learn PHP!&lt;br&gt;&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;This&quot;</span>, <span class="string">&quot; string&quot;</span>, <span class="string">&quot; was&quot;</span>, <span class="string">&quot; made&quot;</span>, <span class="string">&quot; with multiple parameters.&quot;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>上面echo输出结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">PHP is fun!</span><br><span class="line"> </span><br><span class="line">Hello world!</span><br><span class="line">I&#39;m about to learn PHP!</span><br><span class="line">This string was made with multiple parameters.</span><br></pre></td></tr></table></figure><h5 id="显示变量"><a href="#显示变量" class="headerlink" title="显示变量"></a>显示变量</h5><p>下面的实例演示了如何使用 echo 命令输出变量和字符串：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$txt1</span>=<span class="string">&quot;Learn PHP&quot;</span>;</span><br><span class="line"><span class="variable">$txt2</span>=<span class="string">&quot;w3cschool.cn&quot;</span>;</span><br><span class="line"><span class="variable">$cars</span>=<span class="keyword">array</span>(<span class="string">&quot;Volvo&quot;</span>,<span class="string">&quot;BMW&quot;</span>,<span class="string">&quot;Toyota&quot;</span>);</span><br><span class="line"> </span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$txt1</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;&lt;br&gt;&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;Study PHP at <span class="subst">$txt2</span>&quot;</span>; <span class="comment">//这里外面用的是双引号，在php里，双引号是可以解析变量的</span></span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;My car is a <span class="subst">&#123;$cars[0]&#125;</span>&quot;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>上面echo输出结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Learn PHP</span><br><span class="line">Study PHP at w3cschool.cn</span><br><span class="line">My car is a Volvo</span><br></pre></td></tr></table></figure><h3 id="print-语句"><a href="#print-语句" class="headerlink" title="print 语句"></a>print 语句</h3><p>print 同样是一个语言结构，可以使用括号，也可以不使用括号： print 或 print()。</p><h5 id="显示字符串-1"><a href="#显示字符串-1" class="headerlink" title="显示字符串"></a>显示字符串</h5><p>下面的实例演示了如何使用 print 命令输出字符串（字符串可以包含 HTML 标签）：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">print</span> <span class="string">&quot;&lt;h2&gt;PHP is fun!&lt;/h2&gt;&quot;</span>;</span><br><span class="line"><span class="keyword">print</span> <span class="string">&quot;Hello world!&lt;br&gt;&quot;</span>;</span><br><span class="line"><span class="keyword">print</span> <span class="string">&quot;I&#x27;m about to learn PHP!&quot;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">PHP is fun!</span><br><span class="line"> </span><br><span class="line">Hello world!</span><br><span class="line">I&#39;m about to learn PHP!</span><br></pre></td></tr></table></figure><h5 id="显示变量-1"><a href="#显示变量-1" class="headerlink" title="显示变量"></a>显示变量</h5><p>下面的实例演示了如何使用 print 命令输出变量和字符串：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$txt1</span>=<span class="string">&quot;Learn PHP&quot;</span>;</span><br><span class="line"><span class="variable">$txt2</span>=<span class="string">&quot;w3cschool.cn&quot;</span>;</span><br><span class="line"><span class="variable">$cars</span>=<span class="keyword">array</span>(<span class="string">&quot;Volvo&quot;</span>,<span class="string">&quot;BMW&quot;</span>,<span class="string">&quot;Toyota&quot;</span>);</span><br><span class="line"> </span><br><span class="line"><span class="keyword">print</span> <span class="variable">$txt1</span>;</span><br><span class="line"><span class="keyword">print</span> <span class="string">&quot;&lt;br&gt;&quot;</span>;</span><br><span class="line"><span class="keyword">print</span> <span class="string">&quot;Study PHP at <span class="subst">$txt2</span>&quot;</span>;</span><br><span class="line"><span class="keyword">print</span> <span class="string">&quot;My car is a <span class="subst">&#123;$cars[0]&#125;</span>&quot;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Learn PHP</span><br><span class="line">Study PHP at w3cschool.cn</span><br><span class="line">My car is a Volvo</span><br></pre></td></tr></table></figure><h3 id="print-r-语句"><a href="#print-r-语句" class="headerlink" title="print_r 语句"></a>print_r 语句</h3><p>print_r 显示关于一个变量的易于理解的信息,如果给出的是 <code>string</code>、<code>integer</code> 或 <code>float</code>，将打印变量值本身。</p><p>如果给出的是 <code>array</code>，将会按照一定格式显示键和元素。<code>object</code>与数组类似。</p><p>使用时必须加上括号:print_r()。</p><p>小提示:print_r()会将把数组的指针移到最后边。使用 <code>reset() </code>可让指针回到开始处。</p><h5 id="显示字符串-2"><a href="#显示字符串-2" class="headerlink" title="显示字符串"></a>显示字符串</h5><p>下面的实例演示了如何使用 print_r 命令输出字符串（字符串可以包含 HTML 标签）：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">print_r(<span class="string">&quot;Hello World!&quot;</span>);</span><br><span class="line">print_r(<span class="string">&quot;Goodbye World!&quot;</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Hello World! Goodbye World</span><br></pre></td></tr></table></figure><p>显示变量</p><p>下面的实例演示了如何使用 print_r 命令输出变量和字符串：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$txt1</span>=<span class="string">&quot;Hello World!&quot;</span>;</span><br><span class="line"><span class="variable">$cars</span>=<span class="keyword">array</span>(<span class="string">&quot;Volvo&quot;</span>,<span class="string">&quot;BMW&quot;</span>,<span class="string">&quot;Toyota&quot;</span>);</span><br><span class="line"> </span><br><span class="line">print_r(<span class="variable">$txt1</span>);</span><br><span class="line">print_r(<span class="variable">$cars</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Hello World!Array ( [0] &#x3D;&gt; Volvo [1] &#x3D;&gt; BMW [2] &#x3D;&gt; Toyota ) &lt;!-- 后面array是打印的$cars数组 --&gt;</span><br></pre></td></tr></table></figure><h3 id="printf"><a href="#printf" class="headerlink" title="printf"></a>printf</h3><p>printf() 函数输出格式化的字符串。</p><p>arg1、arg2、arg++ 参数将被插入到主字符串中的百分号（%）符号处。该函数是逐步执行的。在第一个 % 符号处，插入 arg1，在第二个 % 符号处，插入 arg2，依此类推。</p><p><strong>注释</strong>：如果 % 符号多于 arg 参数，则您必须使用占位符。占位符被插入到 % 符号之后，由数字和 “$” 组成。</p><h5 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h5><table class="dataintable" style="height: 543px; width: 1233px;"><tbody><tr><th>参数</th><th>描述</th></tr><tr><td><em>format</em></td><td><p>必需。规定字符串以及如何格式化其中的变量。</p><p>可能的格式值：</p><ul class="listintable"><li>%% - 返回一个百分号 %</li><li>%b - 二进制数</li><li>%c - ASCII 值对应的字符</li><li>%d - 包含正负号的十进制数（负数、0、正数）</li><li>%e - 使用小写的科学计数法（例如 1.2e+2）</li><li>%E - 使用大写的科学计数法（例如 1.2E+2）</li><li>%u - 不包含正负号的十进制数（大于等于 0）</li><li>%f - 浮点数（本地设置）</li><li>%F - 浮点数（非本地设置）</li><li>%g - 较短的 %e 和 %f</li><li>%G - 较短的 %E 和 %f</li><li>%o - 八进制数</li><li>%s - 字符串</li><li>%x - 十六进制数（小写字母）</li><li>%X - 十六进制数（大写字母）</li></ul><p>附加的格式值。必需放置在 % 和字母之间（例如 %.2f）：</p><ul class="listintable"><li>+ （在数字前面加上 + 或 - 来定义数字的正负性。默认地，只有负数做标记，正数不做标记）</li><li>' （规定使用什么作为填充，默认是空格。它必须与宽度指定器一起使用。）</li><li>- （左调整变量值）</li><li>[0-9] （规定变量值的最小宽度）</li><li>.[0-9] （规定小数位数或最大字符串长度）</li></ul><p class="note">注释：如果使用多个上述的格式值，它们必须按照上面的顺序进行使用，不能打乱。</p></td></tr><tr><td><em>arg1</em></td><td>必需。规定插到<span class="Apple-converted-space">&nbsp;<em>format</em><span class="Apple-converted-space">&nbsp;字符串中第一个 % 符号处的参数。</span></span></td></tr><tr><td><em>arg2</em></td><td>必需。规定插到<span class="Apple-converted-space">&nbsp;<em>format</em><span class="Apple-converted-space">&nbsp;字符串中第二个 % 符号处的参数。</span></span></td></tr><tr><td><em>arg++</em></td><td>可选。规定插到<span class="Apple-converted-space">&nbsp;<em>format</em><span class="Apple-converted-space">&nbsp;字符串中第三、四等等 % 符号处的参数。</span></span></td></tr></tbody></table><p>提示：相关函数：sprintf()、 vprintf()、 vsprintf()、 fprintf() 和 vfprintf()</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$number</span> = <span class="number">9</span>;</span><br><span class="line"><span class="variable">$str</span> = <span class="string">&quot;北京&quot;</span>;</span><br><span class="line">printf(<span class="string">&quot;在%s有 %u 百万辆自行车。&quot;</span>,<span class="variable">$str</span>,<span class="variable">$number</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line">```　　</span><br><span class="line">运行结果：</span><br></pre></td></tr></table></figure><p>在北京有 9 百万辆自行车。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">使用格式值 %f：</span><br><span class="line"></span><br><span class="line">&#96;&#96;&#96;php</span><br><span class="line">&lt;?php</span><br><span class="line">$number &#x3D; 123;</span><br><span class="line">printf(&quot;%f&quot;,$number);</span><br><span class="line">?&gt;</span><br><span class="line">&#96;&#96;&#96;　　</span><br><span class="line">运行结果：</span><br></pre></td></tr></table></figure><p>123.000000  这里默认省略到小数点后六位</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">使用占位符：</span><br><span class="line"></span><br><span class="line">&#96;&#96;&#96;php</span><br><span class="line">&lt;?php</span><br><span class="line">$number &#x3D; 123;</span><br><span class="line">printf(&quot;有两位小数：%1\$.2f&lt;br&gt;没有小数：%1\$u&quot;,$number);</span><br><span class="line">?&gt;</span><br><span class="line">&#96;&#96;&#96;　　</span><br><span class="line">运行结果：</span><br></pre></td></tr></table></figure><p>有两位小数：123.00<br>没有小数：123</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">**所有可能的格式值的演示：**</span><br><span class="line"></span><br><span class="line">&#96;&#96;&#96;php</span><br><span class="line">&lt;?php</span><br><span class="line">$num1 &#x3D; 123456789;</span><br><span class="line">$num2 &#x3D; -123456789;</span><br><span class="line">$char &#x3D; 50; &#x2F;&#x2F; ASCII 字符 50 是 2</span><br><span class="line"> </span><br><span class="line">&#x2F;&#x2F; 注释：格式值 &quot;%%&quot; 返回百分号</span><br><span class="line">printf(&quot;%%b &#x3D; %b &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 二进制数</span><br><span class="line">printf(&quot;%%c &#x3D; %c &lt;br&gt;&quot;,$char); &#x2F;&#x2F; ASCII 字符</span><br><span class="line">printf(&quot;%%d &#x3D; %d &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 带符号的十进制数</span><br><span class="line">printf(&quot;%%d &#x3D; %d &lt;br&gt;&quot;,$num2); &#x2F;&#x2F; 带符号的十进制数</span><br><span class="line">printf(&quot;%%e &#x3D; %e &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 科学计数法（小写）</span><br><span class="line">printf(&quot;%%E &#x3D; %E &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 科学计数法（大写）</span><br><span class="line">printf(&quot;%%u &#x3D; %u &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 不带符号的十进制数（正）</span><br><span class="line">printf(&quot;%%u &#x3D; %u &lt;br&gt;&quot;,$num2); &#x2F;&#x2F; 不带符号的十进制数（负）</span><br><span class="line">printf(&quot;%%f &#x3D; %f &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 浮点数（视本地设置）</span><br><span class="line">printf(&quot;%%F &#x3D; %F &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 浮点数（不视本地设置）</span><br><span class="line">printf(&quot;%%g &#x3D; %g &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 短于 %e 和 %f</span><br><span class="line">printf(&quot;%%G &#x3D; %G &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 短于 %E 和 %f</span><br><span class="line">printf(&quot;%%o &#x3D; %o &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 八进制数</span><br><span class="line">printf(&quot;%%s &#x3D; %s &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 字符串</span><br><span class="line">printf(&quot;%%x &#x3D; %x &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 十六进制数（小写）</span><br><span class="line">printf(&quot;%%X &#x3D; %X &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 十六进制数（大写）</span><br><span class="line">printf(&quot;%%+d &#x3D; %+d &lt;br&gt;&quot;,$num1); &#x2F;&#x2F; 符号说明符（正）</span><br><span class="line">printf(&quot;%%+d &#x3D; %+d &lt;br&gt;&quot;,$num2); &#x2F;&#x2F; 符号说明符（负）</span><br><span class="line">?&gt;</span><br><span class="line">&#96;&#96;&#96;　　</span><br><span class="line">运行结果：</span><br></pre></td></tr></table></figure><p>%b = 111010110111100110100010101<br>%c = 2<br>%d = 123456789<br>%d = -123456789<br>%e = 1.234568e+8<br>%E = 1.234568E+8<br>%u = 123456789<br>%u = 4171510507<br>%f = 123456789.000000<br>%F = 123456789.000000<br>%g = 1.23457e+8<br>%G = 1.23457E+8<br>%o = 726746425<br>%s = 123456789<br>%x = 75bcd15<br>%X = 75BCD15<br>%+d = +123456789<br>%+d = -123456789</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">##### 字符串说明符的演示：</span><br><span class="line"></span><br><span class="line">&#96;&#96;&#96;php</span><br><span class="line">&lt;?php</span><br><span class="line">$str1 &#x3D; &quot;Hello&quot;;</span><br><span class="line">$str2 &#x3D; &quot;Hello world!&quot;;</span><br><span class="line"> </span><br><span class="line">printf(&quot;[%s]&lt;br&gt;&quot;,$str1);</span><br><span class="line">printf(&quot;[%8s]&lt;br&gt;&quot;,$str1);</span><br><span class="line">printf(&quot;[%-8s]&lt;br&gt;&quot;,$str1);</span><br><span class="line">printf(&quot;[%08s]&lt;br&gt;&quot;,$str1);</span><br><span class="line">printf(&quot;[%&#39;*8s]&lt;br&gt;&quot;,$str1);</span><br><span class="line">printf(&quot;[%8.8s]&lt;br&gt;&quot;,$str2);</span><br><span class="line">?&gt;</span><br></pre></td></tr></table></figure><p>　<br>运行结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[Hello]</span><br><span class="line">[ Hello]</span><br><span class="line">[Hello ]</span><br><span class="line">[000Hello]</span><br><span class="line">[***Hello]</span><br><span class="line">[Hello wo]</span><br></pre></td></tr></table></figure><h3 id="var-dump"><a href="#var-dump" class="headerlink" title="var_dump"></a>var_dump</h3><p> — 打印变量的相关信息，此函数显示关于一个或多个表达式的结构信息，包括表达式的类型与值。数组将递归展开值，通过缩进显示其结构。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$a</span> = <span class="keyword">array</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="keyword">array</span>(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>));</span><br><span class="line">var_dump(<span class="variable">$a</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">array(3) &#123;</span><br><span class="line">  [0]&#x3D;&gt;</span><br><span class="line">  int(1) 前面是类型</span><br><span class="line">  [1]&#x3D;&gt;</span><br><span class="line">  int(2)</span><br><span class="line">  [2]&#x3D;&gt;</span><br><span class="line">  array(3) &#123;</span><br><span class="line">    [0]&#x3D;&gt;</span><br><span class="line">    string(1) &quot;a&quot;</span><br><span class="line">    [1]&#x3D;&gt;</span><br><span class="line">    string(1) &quot;b&quot;</span><br><span class="line">    [2]&#x3D;&gt;</span><br><span class="line">    string(1) &quot;c&quot;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>再来一个例子</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"> </span><br><span class="line"><span class="variable">$b</span> = <span class="number">3.1</span>;</span><br><span class="line"><span class="variable">$c</span> = <span class="literal">true</span>;</span><br><span class="line">var_dump(<span class="variable">$b</span>, <span class="variable">$c</span>);</span><br><span class="line"></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>运行结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">float(3.1)</span><br><span class="line">bool(true)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> background </tag>
            
            <tag> php </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python中文件变化监控</title>
      <link href="python/self_tool/python-listen-dir/"/>
      <url>python/self_tool/python-listen-dir/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>在python中文件监控主要有两个库，一个是<a href="https://github.com/seb-m/pyinotify/wiki">pyinotify</a>，一个是<a href="http://pythonhosted.org/watchdog/">watchdog</a>。pyinotify依赖于Linux平台的inotify，后者则对不同平台的的事件都进行了封装。因为我主要用于Windows平台，所以下面着重介绍watchdog（推荐大家阅读一下watchdog实现源码，有利于深刻的理解其中的原理）。<br>watchdog在不同的平台使用不同的方法进行文件检测。在init.py中发现了如下注释：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">|Inotify|                             Linux 2.6.13+                    &#96;&#96;inotify(7)&#96;&#96; based observer</span><br><span class="line">|FSEvents|                            Mac OS X                         FSEvents based observer</span><br><span class="line">|Kqueue|                              Mac OS X and BSD with kqueue(2)  &#96;&#96;kqueue(2)&#96;&#96; based observer</span><br><span class="line">|WinApi|(ReadDirectoryChangesW)       MS Windows                       Windows API-based observer</span><br><span class="line">|Polling|                             Any                              fallback implementation</span><br></pre></td></tr></table></figure><h3 id="给出示例代码如下："><a href="#给出示例代码如下：" class="headerlink" title="给出示例代码如下："></a>给出示例代码如下：</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by victor</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;检测文件夹变化&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入watchdog对应模块</span></span><br><span class="line"><span class="keyword">from</span> watchdog.observers <span class="keyword">import</span> Observer</span><br><span class="line"><span class="keyword">from</span> watchdog.events <span class="keyword">import</span> *</span><br><span class="line"><span class="comment"># 导入时间模块</span></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">FileEventHandler</span>(<span class="params">FileSystemEventHandler</span>):</span></span><br><span class="line">    <span class="comment"># 初始化魔术方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        FileSystemEventHandler.__init__(self)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 文件或文件夹移动</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_moved</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        <span class="keyword">if</span> event.is_directory:</span><br><span class="line">            print(<span class="string">&quot;directory moved from &#123;0&#125; to &#123;1&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path,event.dest_path))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;file moved from &#123;0&#125; to &#123;1&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path,event.dest_path))</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 创建文件或文件夹</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_created</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        <span class="keyword">if</span> event.is_directory:</span><br><span class="line">            print(<span class="string">&quot;directory created:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;file created:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 删除文件或文件夹</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_deleted</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        <span class="keyword">if</span> event.is_directory:</span><br><span class="line">            print(<span class="string">&quot;directory deleted:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;file deleted:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 移动文件或文件夹</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_modified</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        <span class="keyword">if</span> event.is_directory:</span><br><span class="line">            print(<span class="string">&quot;directory modified:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;file modified:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    <span class="comment"># 实例化Observer对象</span></span><br><span class="line">    observer = Observer()</span><br><span class="line">    event_handler = FileEventHandler()</span><br><span class="line">    <span class="comment"># 设置监听目录</span></span><br><span class="line">    dis_dir = <span class="string">&quot;e:/&quot;</span></span><br><span class="line">    observer.schedule(event_handler,dis_dir,<span class="literal">True</span>)</span><br><span class="line">    observer.start()</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">            <span class="comment"># 设置监听频率(间隔周期时间)</span></span><br><span class="line">            time.sleep(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">except</span> KeyboardInterrupt:</span><br><span class="line">        observer.stop()</span><br><span class="line">    observer.join()</span><br></pre></td></tr></table></figure><h3 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h3><p>watchdog主要采用观察者模型（废话，从变量命名就可以看出来）。主要有三个角色：observer，event_handler，被监控的文件夹。三者原本是独立的，主要通过observer.schedule函数将三者串起来，意思为observer不断检测调用平台依赖代码对监控文件夹进行变动检测，当发现改变时，通知event_handler处理。最后特别推荐读者有时间可以阅读一下watchdog的源码，写的易懂而且架构很好用</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> system </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>在ubuntu下安装mysql数据库</title>
      <link href="database/ubuntu-install-mysql/"/>
      <url>database/ubuntu-install-mysql/</url>
      
        <content type="html"><![CDATA[<div class="content-intro view-box "><p>Ubuntu是一个比较流行的Linux操作系统，不仅简单易用，而且和Windows相容性非常好。那么在ubuntu下如何安装mysql数据库呢？<br></p><p>在Ubuntu上安装mysql数据库，一般分为两种方法，分别是使用Ubuntu&nbsp;Software&nbsp;Center或者apt命令来安装，而且过程都相对比较简单。</p><p><br></p><p><b>1、使用Ubuntu&nbsp;Software&nbsp;Center安装</b></p><p>打开Ubuntu&nbsp;Software&nbsp;Center，在右上角的搜索框查询mysql，然后选定MySQL&nbsp;Server，点击安装即可。</p><p><br></p><p><b>2、使用apt命令安装</b></p><p>打开终端执行&nbsp;”sudo&nbsp;apt-get&nbsp;install&nbsp;mysql-server“&nbsp;即可。</p><p><br></p><p><b>MySQL初始配置</b></p><p>在成功安装mysql后，可以直接使用root账户登录，注意这个账户是默认没有密码的。因此为了数据库的安全，需要第一时间给root用户设置密码。</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">mysql&gt; <span class="hljs-keyword">GRANT</span> ALL <span class="hljs-keyword">PRIVILEGES</span> <span class="hljs-keyword">ON</span> *.* <span class="hljs-keyword">TO</span> root@localhost <span class="hljs-keyword">IDENTIFIED</span> <span class="hljs-keyword">BY</span> <span class="hljs-string">"&lt;password&gt;"</span>;</code></pre><p>将以上命令中的&lt;password&gt;替换为你要设定的密码即可。设置密码后，如果再以root用户登录就需要输入密码了，如：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">$ mysql -u rootERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)$ mysql -u root -pEnter password: Welcome to the MySQL monitor.  Commands <span class="hljs-keyword">end</span> <span class="hljs-keyword">with</span> ; or \g.Your MySQL connection id is 75Server version: 5.5.34-0ubuntu0.13.10.1 (Ubuntu)Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type '<span class="hljs-keyword">help</span>;' or '\h' for help. <span class="hljs-keyword">Type</span> <span class="hljs-string">'\c'</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">clear</span> the <span class="hljs-keyword">current</span> <span class="hljs-keyword">input</span> statement.mysql&gt; </code></pre><p><br></p><p><b>建立数据库独立用户</b></p><p>root用户拥有数据库的所有操作权限，因此不能轻易给别人用。在一个MySQL实例中，我们可以创建多个数据库，而这些数据库可能会分属不同的项目，那么每个数据库的操作角色也就不一样。对此，我们可以针对不同的数据库，去指定用户进行访问。</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">首先使用root角色创建一个数据库mysql&gt; <span class="hljs-keyword">create</span> <span class="hljs-keyword">database</span> db_web_monitor然后将这个数据库授予一个叫xavier的用户使用mysql&gt; <span class="hljs-keyword">GRANT</span> ALL <span class="hljs-keyword">PRIVILEGES</span> <span class="hljs-keyword">ON</span> db_web_monitor.* <span class="hljs-keyword">TO</span> xavier@localhost <span class="hljs-keyword">IDENTIFIED</span> <span class="hljs-keyword">BY</span> <span class="hljs-string">"xavier"</span>;</code></pre><p>这样就可以使用xavier用户，密码为xavier在本机登录MySQL操作db_web_monitor数据库了。</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">$ mysql -u xavierERROR 1045 (28000): Access denied for user 'xavier'@'localhost' (using password: NO)$ mysql -u xavier -pEnter password: Welcome to the MySQL monitor.  Commands <span class="hljs-keyword">end</span> <span class="hljs-keyword">with</span> ; or \g.Your MySQL connection id is 77Server version: 5.5.34-0ubuntu0.13.10.1 (Ubuntu)Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type '<span class="hljs-keyword">help</span>;' or '\h' for help. <span class="hljs-keyword">Type</span> <span class="hljs-string">'\c'</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">clear</span> the <span class="hljs-keyword">current</span> <span class="hljs-keyword">input</span> statement.mysql&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">databases</span>;+<span class="hljs-comment">--------------------+| Database           |+--------------------+| information_schema || db_web_monitor     || test               |+--------------------+3 rows in set (0.00 sec)mysql&gt; </span></code></pre><p><b>开放远程登录权限</b></p><p>1.&nbsp;首先修改MySQL的配置文件，允许监听远程登录。</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">$ sudo vi /etc/mysql/my.cnf找到bind-address所在行 45 # Instead of skip-networking the default is now to listen only on 46 # localhost which is more compatible and is not less secure. 47 bind-address        = 127.0.0.1将 bind-address值修改为本机IP即可。注意注释说明，如果是较老版本的MySQL，此处就应该是skip-networking，直接将其注释即可。</code></pre><p>2.&nbsp;授予用户远程登录权限。</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">mysql&gt;<span class="hljs-keyword">GRANT</span> ALL <span class="hljs-keyword">PRIVILEGES</span> <span class="hljs-keyword">ON</span> db_web_monitor.* <span class="hljs-keyword">TO</span> xavier@<span class="hljs-string">"%"</span> <span class="hljs-keyword">IDENTIFIED</span> <span class="hljs-keyword">BY</span> <span class="hljs-string">"xavier"</span>;</code></pre><p>如此这般，xavier用户就可以在任意主机通过IP访问到本机MySQL，对db_web_monitor数据库进行操作了</p><p><br></p><p><b>推荐阅读：</b></p><p><a href="https://www.w3cschool.cn/ubuntu/" target="_blank">Ubuntu官方帮助文档</a><br></p><p><a href="https://www.w3cschool.cn/mysql/" target="_blank">MySQL教程</a></p><p><br></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> ubuntu </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>mysql修改密码方法</title>
      <link href="database/mysql/mysql-change-pwd/"/>
      <url>database/mysql/mysql-change-pwd/</url>
      
        <content type="html"><![CDATA[<div class="content-intro view-box "><p>在windows系统中，<a href="https://www.w3cschool.cn/mysql/" target="_blank">mysql</a>修改密码的方法还是比较多的。本文就为大家介绍四种MySQL修改root密码的方法。</p><p><br></p><p><b>方法一：用SET&nbsp;PASSWORD命令修改</b></p><p>首先登陆mysql，一般命令格式为：mysql&gt;&nbsp;set&nbsp;password&nbsp;for&nbsp;用户名@localhost&nbsp;=&nbsp;password('新密码');&nbsp;</p><p>例子：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">mysql&gt; <span class="hljs-keyword">set</span> <span class="hljs-keyword">password</span> <span class="hljs-keyword">for</span> root@localhost = <span class="hljs-keyword">password</span>(<span class="hljs-string">'123'</span>); </code></pre><p><br></p><p><b>方法二：用mysqladmin修改</b></p><p>格式：mysqladmin&nbsp;-u用户名&nbsp;-p旧密码&nbsp;password&nbsp;新密码&nbsp;</p><p>例子：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">mysqladmin -uroot -p123456 password 123 </code></pre><p>这个命令就是讲uroot这个用户的密码由p123456改成了123</p><p><br></p><p><b>方法三：用UPDATE直接编辑user表&nbsp;</b></p><p>首先登陆mysql</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">mysql&gt; <span class="hljs-keyword">use</span> mysql; mysql&gt; <span class="hljs-keyword">update</span> <span class="hljs-keyword">user</span> <span class="hljs-keyword">set</span> <span class="hljs-keyword">password</span>=<span class="hljs-keyword">password</span>(<span class="hljs-string">'123'</span>) <span class="hljs-keyword">where</span> <span class="hljs-keyword">user</span>=<span class="hljs-string">'root'</span> <span class="hljs-keyword">and</span> host=<span class="hljs-string">'localhost'</span>; mysql&gt; <span class="hljs-keyword">flush</span> <span class="hljs-keyword">privileges</span>; </code></pre><p>以上的代码是将root的密码更改为123</p><p><br></p><p>以上三种方法都是在记得旧密码的情况下，如果用户忘记了密码，那么该怎么办呢？</p><p><br></p><p><b>方法四：忘记旧密码的修改方法</b></p><p>1.&nbsp;关闭正在运行的MySQL服务。&nbsp;</p><p>2.&nbsp;打开DOS窗口，转到mysql\bin目录。&nbsp;</p><p>3.&nbsp;输入mysqld--skip-grant-tables回车。--skip-grant-tables这个指令是让用户再次启动MySQL服务的时候，可以直接跳过权限表认证。&nbsp;</p><p>4.&nbsp;再开一个DOS窗口（因为刚才那个DOS窗口已经不能动了），然后转到mysql\bin目录。&nbsp;</p><p>5.&nbsp;输入mysql回车，如果成功，将出现MySQL提示符&nbsp;&gt;。&nbsp;</p><p>6.&nbsp;连接权限数据库：&nbsp;use&nbsp;mysql;&nbsp;。&nbsp;</p><p>6.&nbsp;改密码：update&nbsp;user&nbsp;set&nbsp;password=password("123")&nbsp;where&nbsp;user="root";（别忘了最后加分号）&nbsp;。&nbsp;</p><p>7.&nbsp;刷新权限（必须步骤）：flush&nbsp;privileges;　。&nbsp;</p><p>8.&nbsp;退出&nbsp;quit。&nbsp;</p><p>9.&nbsp;注销系统，再进入，使用用户名root和刚才设置的新密码123登录。&nbsp;</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MySQL分页查询方法及优化</title>
      <link href="database/mysql/mysql-paging-query/"/>
      <url>database/mysql/mysql-paging-query/</url>
      
        <content type="html"><![CDATA[<div class="content-intro view-box "><p>当数据库的数据量很大时，一次性查询结果就会变得很慢，为了提高查询效率，我们可以使用MySQL的分页查询功能。本文就为大家带来MySQL分页查询方法及优化。    <br></p><p><br></p><p><b>推荐阅读：</b></p><p><a href="https://www.w3cschool.cn/mysql21minutes/" target="_blank">21分钟MySQL入门教程</a></p><p><a href="https://www.w3cschool.cn/mysql/" target="_blank">MySQL完整教程</a></p><p><br></p><p><b>分页查询方法：</b><br></p><p>在MySQL中，分页查询一般都是使用limit子句实现，limit子句声明如下：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">table</span> <span class="hljs-keyword">LIMIT</span> [<span class="hljs-keyword">offset</span>,] <span class="hljs-keyword">rows</span> | <span class="hljs-keyword">rows</span> <span class="hljs-keyword">OFFSET</span> <span class="hljs-keyword">offset</span></code></pre><p>LIMIT子句可以被用于指定&nbsp;SELECT&nbsp;语句返回的记录数。需注意以下几点：</p><p>1、第一个参数指定第一个返回记录行的偏移量</p><p>2、第二个参数指定返回记录行的最大数目</p><p>3、如果只给定一个参数：它表示返回最大的记录行数目</p><p>4、第二个参数为&nbsp;-1&nbsp;表示检索从某一个偏移量到记录集的结束所有的记录行</p><p>5、初始记录行的偏移量是0(而不是&nbsp;1)</p><p>    <br></p><p>下面是一个应用实例：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">1000</span>,<span class="hljs-number">10</span>;</code></pre><p>该条语句将会从表&nbsp;orders_history&nbsp;中查询第1000条数据之后的10条数据，也就是第1001条到第1010条数据。</p><p>数据表中的记录默认使用主键（一般为id）排序，上面的结果相当于：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">10000</span>,<span class="hljs-number">10</span>;</code></pre><p>三次查询时间分别为：</p><p>3040&nbsp;ms</p><p>3063&nbsp;ms</p><p>3018&nbsp;ms</p><p>针对这种查询方式，下面测试查询记录量对时间的影响：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">10000</span>,<span class="hljs-number">1</span>;<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">10000</span>,<span class="hljs-number">10</span>;<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">10000</span>,<span class="hljs-number">100</span>;<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">10000</span>,<span class="hljs-number">1000</span>;<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">10000</span>,<span class="hljs-number">10000</span>;</code></pre><p>三次查询时间如下：</p><p>查询1条记录：3072ms&nbsp;3092ms&nbsp;3002ms</p><p>查询10条记录：3081ms&nbsp;3077ms&nbsp;3032ms</p><p>查询100条记录：3118ms&nbsp;3200ms&nbsp;3128ms</p><p>查询1000条记录：3412ms&nbsp;3468ms&nbsp;3394ms</p><p>查询10000条记录：3749ms&nbsp;3802ms&nbsp;3696ms</p><p>另外我还做了十来次查询，从查询时间来看，基本可以确定，在查询记录量低于100时，查询时间基本没有差距，随着查询记录量越来越大，所花费的时间也会越来越多。</p><p>    <br></p><p>针对查询偏移量的测试：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">100</span>,<span class="hljs-number">100</span>;<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">1000</span>,<span class="hljs-number">100</span>;<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">10000</span>,<span class="hljs-number">100</span>;<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">100000</span>,<span class="hljs-number">100</span>;<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">1000000</span>,<span class="hljs-number">100</span>;</code></pre><p>三次查询时间如下：</p><p>查询100偏移：25ms&nbsp;24ms&nbsp;24ms</p><p>查询1000偏移：78ms&nbsp;76ms&nbsp;77ms</p><p>查询10000偏移：3092ms&nbsp;3212ms&nbsp;3128ms</p><p>查询100000偏移：3878ms&nbsp;3812ms&nbsp;3798ms</p><p>查询1000000偏移：14608ms&nbsp;14062ms&nbsp;14700ms</p><p>随着查询偏移的增大，尤其查询偏移大于10万以后，查询时间急剧增加。</p><p>这种分页查询方式会从数据库第一条记录开始扫描，所以越往后，查询速度越慢，而且查询的数据越多，也会拖慢总查询速度。</p><p>    <br></p><p><b>使用子查询优化</b></p><p>这种方式先定位偏移位置的&nbsp;id，然后往后查询，这种方式适用于&nbsp;id&nbsp;递增的情况。</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">100000</span>,<span class="hljs-number">1</span>;<p><span class="hljs-keyword">select</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">100000</span>,<span class="hljs-number">1</span>;</p><p><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">and</span><br><span class="hljs-keyword">id</span>&gt;=(<span class="hljs-keyword">select</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">100000</span>,<span class="hljs-number">1</span>)<br><span class="hljs-keyword">limit</span> <span class="hljs-number">100</span>;</p><p><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">8</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">100000</span>,<span class="hljs-number">100</span>;</code></pre></p><p>4条语句的查询时间如下：</p><p>第1条语句：3674ms</p><p>第2条语句：1315ms</p><p>第3条语句：1327ms</p><p>第4条语句：3710ms</p><p>针对上面的查询需要注意：</p><p>1、比较第1条语句和第2条语句：使用&nbsp;select&nbsp;id&nbsp;代替&nbsp;select&nbsp;*&nbsp;速度增加了3倍</p><p>2、比较第2条语句和第3条语句：速度相差几十毫秒</p><p>3、比较第3条语句和第4条语句：得益于&nbsp;select&nbsp;id&nbsp;速度增加，第3条语句查询速度增加了3倍</p><p>这种方式相较于原始一般的查询方法，将会增快数倍。</p><p>    <br></p><p><b>使用&nbsp;id&nbsp;限定优化</b></p><p>这种方式假设数据表的id是连续递增的，则我们根据查询的页数和查询的记录数可以算出查询的id的范围，可以使用&nbsp;id&nbsp;between&nbsp;and&nbsp;来查询：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">type</span>=<span class="hljs-number">2</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">between</span> <span class="hljs-number">1000000</span> <span class="hljs-keyword">and</span> <span class="hljs-number">1000100</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">100</span>;</code></pre><p>查询时间：15ms&nbsp;12ms&nbsp;9ms</p><p>这种查询方式能够极大地优化查询速度，基本能够在几十毫秒之内完成。限制是只能使用于明确知道id的情况，不过一般建立表的时候，都会添加基本的id字段，这为分页查询带来很多便利。</p><p>还可以有另外一种写法：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span> &gt;= <span class="hljs-number">1000001</span> <span class="hljs-keyword">limit</span> <span class="hljs-number">100</span>;</code></pre><p>当然还可以使用&nbsp;in&nbsp;的方式来进行查询，这种方式经常用在多表关联的时候进行查询，使用其他表查询的id集合，来进行查询：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> orders_history <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">in</span>(<span class="hljs-keyword">select</span> order_id <span class="hljs-keyword">from</span> trade_2 <span class="hljs-keyword">where</span> goods = <span class="hljs-string">'pen'</span>)<span class="hljs-keyword">limit</span> <span class="hljs-number">100</span>;</code></pre><p>这种&nbsp;in&nbsp;查询的方式要注意：某些&nbsp;mysql&nbsp;版本不支持在&nbsp;in&nbsp;子句中使用&nbsp;limit。</p><p>    <br></p><p><b>关于数据表的id说明</b></p><p>一般情况下，在数据库中建立表的时候，每一张表强制添加&nbsp;id&nbsp;递增字段，这样更方便我们查询数据。</p><p>如果数据量很大，比如像订单这类，一般会推荐进行分库分表。这个时候 id 就不建议作为唯一标识了，而应该使用分布式的高并发唯一&nbsp;id&nbsp;生成器来生成，并在数据表中使用另外的字段来存储这个唯一标识。</p><p>首先使用范围查询定位&nbsp;id&nbsp;（或者索引），然后再使用索引进行定位数据，即先&nbsp;select&nbsp;id，然后在&nbsp;select&nbsp;*；这样查询的速度将会提升好几倍。</p><p><br></p><p>原文地址：<a rel="nofollow" href="http://uusama.com/458.html" target="_blank" style="background-color: rgb(255, 255, 255);">http://uusama.com/458.html</a></p><p><br></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MySQL中交集和差集</title>
      <link href="database/mysql/mysql-set/"/>
      <url>database/mysql/mysql-set/</url>
      
        <content type="html"><![CDATA[<div class="content-intro view-box "><p>在MySQL中，只支持Union(并集)集合运算，而对于交集Intersect和差集Except并不支持。那么如何才能在MySQL中实现交集和差集呢？    <br></p><p><br></p><p>一般在MySQL中，我们可以通过in和not&nbsp;in来间接实现交集和差集，当然也有一定局限性，面对少量数据还可以，但数据量大了效率就会变得很低。</p><p>创建table1</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-comment">/*DDL 信息*/</span><span class="hljs-comment">------------  </span>  <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`t1`</span> (    <span class="hljs-string">`id`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,    <span class="hljs-string">`name`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,    <span class="hljs-string">`age`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,    PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>)  ) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8  </code></pre><p>创建table2</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-comment">/*DDL 信息*/</span><span class="hljs-comment">------------  </span>  <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`t2`</span> (    <span class="hljs-string">`id`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,    <span class="hljs-string">`name`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,    <span class="hljs-string">`age`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,    PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>)  ) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8  </code></pre><p>插入</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> t1 <span class="hljs-keyword">VALUES</span>(<span class="hljs-number">1</span>,<span class="hljs-string">'小王'</span>,<span class="hljs-number">10</span>);  <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> t1 <span class="hljs-keyword">VALUES</span>(<span class="hljs-number">2</span>,<span class="hljs-string">'小宋'</span>,<span class="hljs-number">20</span>);  <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> t1 <span class="hljs-keyword">VALUES</span>(<span class="hljs-number">3</span>,<span class="hljs-string">'小白'</span>,<span class="hljs-number">30</span>);  <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> t1 <span class="hljs-keyword">VALUES</span>(<span class="hljs-number">4</span>,<span class="hljs-string">'hello'</span>,<span class="hljs-number">40</span>);      <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> t2 <span class="hljs-keyword">VALUES</span>(<span class="hljs-number">1</span>,<span class="hljs-string">'小王'</span>,<span class="hljs-number">10</span>);  <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> t2 <span class="hljs-keyword">VALUES</span>(<span class="hljs-number">2</span>,<span class="hljs-string">'小宋'</span>,<span class="hljs-number">22</span>);  <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> t2 <span class="hljs-keyword">VALUES</span>(<span class="hljs-number">3</span>,<span class="hljs-string">'小肖'</span>,<span class="hljs-number">31</span>);  <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> t2 <span class="hljs-keyword">VALUES</span>(<span class="hljs-number">4</span>,<span class="hljs-string">'hello'</span>,<span class="hljs-number">40</span>);  </code></pre><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">SELECT</span> t1.* <span class="hljs-keyword">FROM</span> t1     <span class="hljs-keyword">id</span>  <span class="hljs-keyword">name</span>    age  <span class="hljs-number">1</span>   小王      <span class="hljs-number">10</span>  <span class="hljs-number">2</span>   小宋      <span class="hljs-number">20</span>  <span class="hljs-number">3</span>   小白      <span class="hljs-number">30</span>  <span class="hljs-number">4</span>   hello   <span class="hljs-number">40</span>  </code></pre><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">SELECT</span> t2.* <span class="hljs-keyword">FROM</span> t2     <span class="hljs-keyword">id</span>  <span class="hljs-keyword">name</span>    age  <span class="hljs-number">1</span>   小王  <span class="hljs-number">10</span>  <span class="hljs-number">2</span>   小宋  <span class="hljs-number">22</span>  <span class="hljs-number">3</span>   小肖  <span class="hljs-number">31</span>  <span class="hljs-number">4</span>   hello   <span class="hljs-number">40</span>  </code></pre><p>使用not&nbsp;in&nbsp;求差集，但效率低</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">SELECT</span> t1.* <span class="hljs-keyword">FROM</span> t1   <span class="hljs-keyword">WHERE</span>   <span class="hljs-keyword">name</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">IN</span>  (<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">name</span> <span class="hljs-keyword">FROM</span> t2)    <span class="hljs-keyword">id</span>  <span class="hljs-keyword">name</span>    age  <span class="hljs-number">3</span>   小白      <span class="hljs-number">30</span>  </code></pre><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">SELECT</span> t1.id, t1.name, t1.age  <span class="hljs-keyword">FROM</span> t1   <span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> t2   <span class="hljs-keyword">ON</span> t1.id = t2.id  <span class="hljs-keyword">WHERE</span> t1.name != t2.name       <span class="hljs-keyword">OR</span> t1.age != t2.age;      id  name    age  2   小宋      20  3   小白      30  </code></pre><p>求交集，此时只有id&nbsp;name&nbsp;age&nbsp;所有都一样才是符合要求的。</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">SELECT</span>  <span class="hljs-keyword">id</span>,  <span class="hljs-keyword">NAME</span>,  age, <span class="hljs-keyword">COUNT</span>(*)      <span class="hljs-keyword">FROM</span> (<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">id</span>, <span class="hljs-keyword">NAME</span>, age          <span class="hljs-keyword">FROM</span> t1                    <span class="hljs-keyword">UNION</span> ALL                    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">id</span>, <span class="hljs-keyword">NAME</span>, age          <span class="hljs-keyword">FROM</span> t2          ) a      <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> <span class="hljs-keyword">id</span>, <span class="hljs-keyword">NAME</span>, age      <span class="hljs-keyword">HAVING</span> <span class="hljs-keyword">COUNT</span>(*) &gt; <span class="hljs-number">1</span>            <span class="hljs-keyword">id</span>  <span class="hljs-keyword">NAME</span>    age <span class="hljs-keyword">COUNT</span>(*)      <span class="hljs-number">1</span>   小王      <span class="hljs-number">10</span>  <span class="hljs-number">2</span>      <span class="hljs-number">4</span>   hello   <span class="hljs-number">40</span>  <span class="hljs-number">2</span>  </code></pre><p><b><br></b></p><p><b>union&nbsp;all和union的区别</b></p><p>UNION和UNION&nbsp;ALL的功能都是将两个结果集合并为一个，但是这两个关键字不管从使用还是效率上来说，都是有一定区别的。</p><p>使用上：</p><p>1、对重复结果的处理：UNION在进行表链接后会筛选掉重复的记录，而Union&nbsp;All则不会去除重复记录。</p><p>2、对排序的处理：Union将会按照字段的顺序进行排序；UNION&nbsp;ALL只是将两个结果合并后就返回，并不会进行排序处理。</p><p>效率上：</p><p>从效率上说，UNION&nbsp;ALL的处理效率要比UNION高很多，所以，如果可以确认合并的两个结果集中，且不包含重复数据和不需要进行排序的话，推荐使用UNION&nbsp;ALL。</p><p>    <br></p><p><b>相关阅读：</b></p><p><a href="https://www.w3cschool.cn/mysql_migration/" target="_blank">不同场景下&nbsp;MySQL&nbsp;的迁移方案</a></p><p><a href="https://www.w3cschool.cn/hjikt5/" target="_blank">MySQL&nbsp;FAQ系列整理</a></p><p><br></p><p>原文地址：<a rel="nofollow" href="https://blog.csdn.net/mine_song/article/details/70184072" target="_blank">https://blog.csdn.net/mine_song/article/details/70184072</a></p><p>    <br></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>几个优秀的mysql管理工具与应用程序推荐</title>
      <link href="database/mysql/mysql-tools/"/>
      <url>database/mysql/mysql-tools/</url>
      
        <content type="html"><![CDATA[<div class="content-intro view-box "><p>对于开发人员来说，mysql管理工具可以说是必不可缺的，它能帮助开发人员在许多方面支持包括PostgreSQL、MySQL、Redis、MongoDB等在内的多种数据库；同时还能提供包括触发器、事件、视图、数据备份、对象结构等多种功能。<br></p><p>本文帮大家整理了15款优秀的MySQL管理工具和应用软件，大家可以从中选择一个，从而帮助你轻松快速完成工作。</p><p><br></p><p><b>1.&nbsp;Induction</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637403288180.jpg" alt="1" class=""><b><br></b></p><p>Induction是一款用于理解数据关系的开源管理工具，它可用来探索行/列，运行查询和数据可视化等方面。该工具支持PostgreSQL、<a href="https://www.w3cschool.cn/mysql/" target="_blank">MySQL</a>、<a href="https://www.w3cschool.cn/sqlite/" target="_blank">SQLite</a>、<a href="https://www.w3cschool.cn/redis/" target="_blank">Redis</a>及<a href="https://www.w3cschool.cn/mongodb/" target="_blank">MongoDB</a>等数据库。此外，Induction还可以通过编写添加其他新的适配器。</p><p><br></p><p><b>2.&nbsp;Pinba</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637411691724.jpg" alt="2" class=""><br></p><p>Pinba&nbsp;是一种MySQL存储引擎，其功能在于PHP实时监控和数据服务器的MySQL只读接口。它会对通过UDP发送的数据进行整理和处理整，并将多个PHP进程通过可读的简单报告的形式加以统计显示。为了获取下一代更为复杂的报告和统计数据，Pinba提供了原始数据的只读接口。</p><p><br></p><p><b>3.&nbsp;DB&nbsp;Ninja</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637420193788.jpg" alt="3" class=""><br></p><p>DbNinja是款基于Web的MySQL数据库管理与开发应用程序，非常适合用来远程访问托管服务器。DbNinja支持包括触发器、事件、视图、存储过程和外键等最新功能。此外,它还可以导入和备份数据、MySQL对象结构以及管理用户等。DbNinj的用户界面不仅美观而且功能很齐全，可在任何浏览器及操作系统中安全运行。</p><p><br></p><p><b>4.&nbsp;DB&nbsp;Tools&nbsp;Manager</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637429931579.jpg" alt="4" class=""><br></p><p>DBManager是一款功能强大的数据管理应用程序，它支持MySQL、PostgreSQL、Interbase/Firebird、SQLite,DBF表、<a href="https://www.w3cschool.cn/ms_access/" target="_blank">MSAccess</a>,MSSQL服务器,Sybase,Oracle和ODBC数据库引擎等一些新特性。目前，DBManager有个人和企业两种版本，用户可以自行选择。</p><p><br></p><p><b>5.&nbsp;Dbeaver</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637439840207.jpg" alt="5" class=""><br></p><p>DBeaver是一款数据库管理应用程序，可运用于多种不同的引擎，包括MySQL，MSSQL，Oracle、SQLite、Sybase和Firebird等等，而且最关键的是它是免费的。DBeaver由Java编写而成，适用于当下所有主流操作系统。它能处理的任务很多，包括元数据编辑(表、列、键、索引)、自定义SQL执行、用户管理、多连接等。</p><p><br></p><p><b>6.&nbsp;SqlWave</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637462485809.jpg" alt="6" class=""><b><br></b></p><p>SQLWave是一种简单易用的MySQL客户端，通过该工具用户可以轻松地连接到远程主机。SqlWave支持所有MySQL的最新版本，用它可以管理数据库结构的所有最新功能，包括工作表、视图、存储过程、函数、事件、外键和触发器等。</p><p><br></p><p><b>7.&nbsp;MyWebSQL</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637473379989.jpg" alt="7" class=""><b><br></b></p><p>MyWebSQL主要用于管理基于Web的MySQL数据库。使用该工具，用户无需切换网页即可完成一些简单的操作。如果您正在操作桌面，只用登数据库，就可以管理您的数据库了。</p><p><br></p><p><b>8.&nbsp;Navicat</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637480520206.jpg" alt="8" class=""><br></p><p>Navicat是MySQL和<a href="https://www.w3cschool.cn/mariadb/" target="_blank">MariaDB</a>数据库管理与开发理想的解决方案。它可以实现在一个应用程序上同时连接MySQL和MariaDB数据库，这为数据库提供了一个直观而强大的图形界面管理、开发和维护功能，是非常适合初级MySQL和MariaDB开发人员和专业开发人员的开发工具。</p><p><br></p><p><b>9.&nbsp;SQLyog</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637530337272.jpg" alt="9" class=""><b><br></b></p><p>SQLyog作为MySQL管理工具的功能非常强大，它结合了MySQL工作台、php&nbsp;MyAdmin和其他MySQL前端及MySQL&nbsp;GUI工具的特点。该款应用程序可以同时连接任意数量级的MySQL服务器，用于测试和生产。所有流程仅需登录MySQL&nbsp;root以收集数据，用户无需安装在MySQL服务器上。</p><p><br></p><p><b>10.&nbsp;Sequel&nbsp;Pro</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637539192113.jpg" alt="10" class=""><br></p><p>Sequel&nbsp;Pro是基于MySQL数据库的一种快速易用的Mac数据库管理应用程序。用户可通过Sequel&nbsp;Pro在本地和远程服务器上直接访问MySQL数据库。不过，Sequel&nbsp;Pro的最新版本开始添加全屏支持内置。</p><p><br></p><p><b>11.&nbsp;HeidiSQL</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637559606018.jpg" alt="11" class=""><b><br></b></p><p>HeidiSQL是一种专为web开发人员设计的有用且可靠的工具，可用于当前最受欢迎的MySQL服务器，微软SQL数据库和PostgreSQL。该工具可提供浏览和编辑数据、创建和编辑表格、视图、过程、触发器和日志安排等事件。此外，您还可以导出结构和数据至SQL文件、剪贴板或其他服务器。</p><p><br></p><p><b>12.&nbsp;MyDB&nbsp;Studio</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637574978811.jpg" alt="12" class=""><b><br></b></p><p>MyDB&nbsp;Studio是一款免费的MySQL数据库管理器应用程序。该工具强大到您几乎可以获取到任何想要的功能，并能够连接到无限量级的数据库。通过创建、编辑或删除数据库、表格和记录，就可以备份/恢复并导出为多个格式。</p><p><br></p><p><b>13.&nbsp;SQL&nbsp;Lite&nbsp;Manger</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637597924795.jpg" alt="13" class=""><b><br></b></p><p>SQL&nbsp;Lite&nbsp;Manager是一款基于web的开源应用程序，用于管理无服务器、零配置SQL&nbsp;Lite数据库。该程序是用PHP写成，除了记录和应用表格格上的每一步操作，还可以控制多个数据库。SQL&nbsp;Lite&nbsp;Manager可用于查询数据，将MySQL查询转化为兼容SQL&nbsp;Lite数据库，并能创建和编辑触发器。SQL&nbsp;Lite&nbsp;Manager有多种皮肤选项，是一个含现成语言文件的多语言资源。</p><p><br></p><p><b>14.&nbsp;Database&nbsp;Master</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637605439152.jpg" alt="14" class=""><b><br></b></p><p>Database&nbsp;Master是一个现代的、强大的、直观且易用的数据库管理程序。它以一个一致而现代的界面适用于MongoDB、MySQL、PostgreSQL、FireBird、&nbsp;SQL&nbsp;Lite、MS&nbsp;SQL&nbsp;Server、SQL&nbsp;Azure、Oracle、IBM&nbsp;DB2、IBM&nbsp;Informix、Netezza、Ingres以及EffiProz等数据库。Database&nbsp;Master简化了管理、查询、编辑、可视化、设计和报告数据库系统。用户可以通过ODBC与OleDB连接任何数据库系统，也可以访问MS&nbsp;Access，MS&nbsp;FoxPro&nbsp;Database、Dbase和XML文件。</p><p><br></p><p><b>15.&nbsp;Chive</b></p><p align="center" style="text-align: center;"><img src= "/img/loading.gif" data-lazy-src="https://atts.w3cschool.cn/attachments/image/20180425/1524637611448384.jpg" alt="15" class=""><b><br></b></p><p>Chive由PHP搭建而成，是一款基于web的开源MySQL管理应用程序。此款应用程式有一个内置的编辑器，当运行复杂的查询或易用的界面时，可用于快速浏览。</p><p>以上就是w3cschool为大家整理的15款优秀的MySQL管理工具和应用软件，希望大家喜欢。</p><p><br></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>mysql中的通配符使用</title>
      <link href="database/mysql/mysql-universal-symbol/"/>
      <url>database/mysql/mysql-universal-symbol/</url>
      
        <content type="html"><![CDATA[<div class="content-intro view-box "><p>在mysql查询中，经常会用到通配符，而且mysql的通配符和pgsql是有所不同的，甚至mysql中还可以使用正则表达式。本文就为大家带来mysql查询中通配符的使用。    <br></p><p>    <br></p><p><b>SQL模式匹配：</b></p><p>“_”&nbsp;匹配单个字符,”\_”&nbsp;匹配”_”</p><p>“%”&nbsp;匹配任意个字符,包括零个字符</p><p>sql模式下的匹配，缺省是对于字母的大小写没有要求，并且sql模式下，“=”或”!=”是不能在模糊匹配中使用的，而是使用&nbsp;like&nbsp;或&nbsp;not&nbsp;like.</p><p>例如：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> ［<span class="hljs-keyword">user</span>］ <span class="hljs-keyword">WHERE</span> u_name <span class="hljs-keyword">LIKE</span> ‘%三%’;<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> ［<span class="hljs-keyword">user</span>］ <span class="hljs-keyword">WHERE</span> u_name <span class="hljs-keyword">LIKE</span> ‘_三_’;</code></pre><p>    <br></p><p><b>正则模式匹配：</b></p><p>当使用正则匹配时，使用REGEXP和NOT&nbsp;REGEXP操作符（或RLIKE和NOT&nbsp;RLIKE，功能是一样的）。</p><p>其中涉及到的字符是：</p><p>“.”&nbsp;匹配任何单个的字符。</p><p>“[…]” 表示匹配在方括号内的任何字符。如，”[abc]”&nbsp;则匹配”a”、”b”或者”c”，“［a-z］”匹配任何小写字母，而“［0-9］”匹配任何数字。</p><p>“&nbsp;*&nbsp;”表示匹配零个或多个在它前面的东西。例如，“x*”匹配任何数量的“x”字符，“［0-9］*”匹配的任何数量的数字，而“.*”匹配任何数量的任何东西。</p><p><font color="#ff0000">注意：正则表达式是区分大小写的</font>，但是我们也能使用一个字符类匹配两种写法。例如，“［aA］”匹配小写或大写的“a”而“［a-zA-Z］”匹配两种写法的任何字母。</p><p>为了定位一个模式以便它必须匹配被测试值的开始或结尾，在模式开始处使用“^”或在模式的结尾用“$”。</p><p>例如：</p><p>—&nbsp;查寻以&nbsp;三&nbsp;开头的名字</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">FROM ［user］ WHERE u_name REGEXP ‘^三’;</code></pre><p>—&nbsp;查寻以&nbsp;三&nbsp;结尾的名字</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">FROM ［user］ WHERE u_name REGEXP ‘三$’;</code></pre><p>—&nbsp;“重复n次”操作符重写先前的查询：</p><pre lang="sql" style="max-width: 100%;"><code class="sql hljs">FROM ［user］ WHERE u_name REGEXP ‘b&#123;2&#125;$’;</code></pre><p><b>推荐阅读：</b></p><p><a href="https://www.w3cschool.cn/regexp/krli1pr3.html" target="_blank">MySQL正则表达式</a></p><p><a href="https://www.w3cschool.cn/mysql/mysql-tutorial.html" target="_blank">MySQL&nbsp;入门教程</a></p><p>    <br></p><p>原文地址：<a rel="nofollow" href="http://www.iamlintao.com/" style="background-color: rgb(255, 255, 255);">26点的博客</a>&nbsp;»&nbsp;<a rel="nofollow" href="http://www.iamlintao.com/2328.html" style="background-color: rgb(255, 255, 255);">mysql查询中通配符的使用</a></p><p>    <br></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Flask 概述</title>
      <link href="python/flask/flask-introduction/"/>
      <url>python/flask/flask-introduction/</url>
      
        <content type="html"><![CDATA[<h3 id="什么是Web-Framework？"><a href="#什么是Web-Framework？" class="headerlink" title="什么是Web Framework？"></a>什么是Web Framework？</h3><p>Web Application Framework（Web应用程序框架）或简单的Web Framework（Web框架）表示一个库和模块的集合，使Web应用程序开发人员能够编写应用程序，而不必担心协议，线程管理等低级细节。</p><h3 id="什么是Flask？"><a href="#什么是Flask？" class="headerlink" title="什么是Flask？"></a>什么是Flask？</h3><p>Flask是一个用Python编写的Web应用程序框架。 它由 Armin Ronacher 开发，他领导一个名为Pocco的国际Python爱好者团队。 Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。两者都是Pocco项目。</p><h3 id="WSGI"><a href="#WSGI" class="headerlink" title="WSGI"></a>WSGI</h3><p>Web Server Gateway Interface（Web服务器网关接口，WSGI）已被用作Python Web应用程序开发的标准。 WSGI是Web服务器和Web应用程序之间通用接口的规范。</p><h3 id="Werkzeug"><a href="#Werkzeug" class="headerlink" title="Werkzeug"></a>Werkzeug</h3><p>它是一个WSGI工具包，它实现了请求，响应对象和实用函数。 这使得能够在其上构建web框架。 Flask框架使用Werkzeug作为其基础之一。</p><h3 id="jinja2"><a href="#jinja2" class="headerlink" title="jinja2"></a>jinja2</h3><p>jinja2是Python的一个流行的模板引擎。Web模板系统将模板与特定数据源组合以呈现动态网页。</p><p>Flask通常被称为微框架。 它旨在保持应用程序的核心简单且可扩展。Flask没有用于数据库处理的内置抽象层，也没有形成验证支持。相反，Flask支持扩展以向应用程序添加此类功能。一些受欢迎的Flask扩展将在本教程后续章节进行讨论。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> flask </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Spring 概述</title>
      <link href="java/javase/spring-introduce/"/>
      <url>java/javase/spring-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p>Spring 是最受欢迎的企业级 Java 应用程序开发框架，数以百万的来自世界各地的开发人员使用 Spring 框架来创建性能好、易于测试、可重用的代码。</p><p>Spring 框架是一个开源的 Java 平台，它最初是由 Rod Johnson 编写的，并且于 2003 年 6 月首次在 Apache 2.0 许可下发布。</p><p>Spring 是轻量级的框架，其基础版本只有 2 MB 左右的大小。</p><p>Spring 框架的核心特性是可以用于开发任何 Java 应用程序，但是在 Java EE 平台上构建 web 应用程序是需要扩展的。 Spring 框架的目标是使 J2EE 开发变得更容易使用，通过启用基于 POJO 编程模型来促进良好的编程实践。</p><h3 id="使用-Spring-框架的好处"><a href="#使用-Spring-框架的好处" class="headerlink" title="使用 Spring 框架的好处"></a>使用 Spring 框架的好处</h3><p>下面列出的是使用 Spring 框架主要的好处：</p><p>Spring 可以使开发人员使用 POJOs 开发企业级的应用程序。只使用 POJOs 的好处是你不需要一个 EJB 容器产品，比如一个应用程序服务器，但是你可以选择使用一个健壮的 servlet 容器，比如 Tomcat 或者一些商业产品。</p><p>Spring 在一个单元模式中是有组织的。即使包和类的数量非常大，你只要担心你需要的，而其它的就可以忽略了。</p><p>Spring 不会让你白费力气做重复工作，它真正的利用了一些现有的技术，像ORM 框架、日志框架、JEE、Quartz 和 JDK 计时器，其他视图技术。</p><p>测试一个用 Spring 编写的应用程序很容易，因为环境相关的代码被移动到这个框架中。此外，通过使用 JavaBean-style POJOs，它在使用依赖注入注入测试数据时变得更容易。</p><p>Spring 的 web 框架是一个设计良好的 web MVC 框架，它为比如 Structs 或者其他工程上的或者不怎么受欢迎的 web 框架提供了一个很好的供替代的选择。MVC模式导致应用程序的不同方面(输入逻辑，业务逻辑和UI逻辑)分离，同时提供这些元素之间的松散耦合。</p><p>模型(Model)封装了应用程序数据，通常它们将由POJO类组成。<br>视图(View)负责渲染模型数据，一般来说它生成客户端浏览器可以解释HTML输出。<br>控制器(Controller)负责处理用户请求并构建适当的模型，并将其传递给视图进行渲染。<br>Spring 对JavaEE开发中非常难用的一些API（JDBC、JavaMail、远程调用等），都提供了封装，使这些API应用难度大大降低。</p><p>轻量级的 IOC 容器往往是轻量级的，例如，特别是当与 EJB 容器相比的时候。这有利于在内存和 CPU 资源有限的计算机上开发和部署应用程序。</p><p>Spring提供了一致的事务管理接口，可向下扩展到（使用一个单一的数据库，例如）本地事务并扩展到全局事务（例如，使用 JTA）。</p><h3 id="依赖注入（DI）"><a href="#依赖注入（DI）" class="headerlink" title="依赖注入（DI）"></a>依赖注入（DI）</h3><p>Spring 最认同的技术是控制反转的依赖注入（DI）模式。控制反转（IoC）是一个通用的概念，它可以用许多不同的方式去表达，依赖注入仅仅是控制反转的一个具体的例子。</p><p>当编写一个复杂的 Java 应用程序时，应用程序类应该尽可能的独立于其他的 Java 类来增加这些类可重用可能性，当进行单元测试时，可以使它们独立于其他类进行测试。依赖注入（或者有时被称为配线）有助于将这些类粘合在一起，并且在同一时间让它们保持独立。</p><p>到底什么是依赖注入？让我们将这两个词分开来看一看。这里将依赖关系部分转化为两个类之间的关联。例如，类 A 依赖于类 B。现在，让我们看一看第二部分，注入。所有这一切都意味着类 B 将通过 IoC 被注入到类 A 中。</p><p>依赖注入可以以向构造函数传递参数的方式发生，或者通过使用 setter 方法 post-construction。由于依赖注入是 Spring 框架的核心部分，所以我将在一个单独的章节中利用很好的例子去解释这一概念。</p><h3 id="面向方面的程序设计（AOP）："><a href="#面向方面的程序设计（AOP）：" class="headerlink" title="面向方面的程序设计（AOP）："></a>面向方面的程序设计（AOP）：</h3><p>Spring 框架的一个关键组件是面向方面的程序设计（AOP）框架。一个程序中跨越多个点的功能被称为横切关注点，这些横切关注点在概念上独立于应用程序的业务逻辑。有各种各样常见的很好的关于方面的例子，比如日志记录、声明性事务、安全性，和缓存等等。</p><p>在 OOP 中模块化的关键单元是类，而在 AOP 中模块化的关键单元是方面。AOP 帮助你将横切关注点从它们所影响的对象中分离出来，然而依赖注入帮助你将你的应用程序对象从彼此中分离出来。</p><p>Spring 框架的 AOP 模块提供了面向方面的程序设计实现，可以定义诸如方法拦截器和切入点等，从而使实现功能的代码彻底的解耦出来。使用源码级的元数据，可以用类似于.Net属性的方式合并行为信息到代码中。我将在一个独立的章节中讨论更多关于 Spring AOP 的概念。</p>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MySQL ERROR 1698 (28000) 错误</title>
      <link href="database/mysql/mysql-error1698/"/>
      <url>database/mysql/mysql-error1698/</url>
      
        <content type="html"><![CDATA[<div id="cnblogs_post_body" class="blogpost-body ">    <h3>之前MySQL服务端本机上使用密码登陆root账号是没有问题的，但是今天不知道是因为动了哪里，登陆失败并有这个错误代码：</h3><div class="cnblogs_code"><pre>~$ mysql -u root -<span style="color: #000000;">pEnter password: ERROR </span><span style="color: #800080;">1698</span> (<span style="color: #800080;">28000</span>): Access denied <span style="color: #0000ff;">for</span> user <span style="color: #800000;">'</span><span style="color: #800000;">root</span><span style="color: #800000;">'</span>@<span style="color: #800000;">'</span><span style="color: #800000;">localhost</span><span style="color: #800000;">'</span></pre></div><p>&nbsp;&nbsp;</p><h3>解决步骤：</h3><p>停止mysql服务</p><div class="cnblogs_code"><pre>~$ <span style="color: #0000ff;">sudo</span> service mysql stop</pre></div><p>&nbsp;</p><p>以安全模式启动MySQL</p><div class="cnblogs_code"><pre>~$ <span style="color: #0000ff;">sudo</span> mysqld_safe --skip-grant-tables &amp;</pre></div><p>&nbsp;</p><h3>MySQL启动之后就可以不用密码登陆了</h3><div class="cnblogs_code"><pre>~$ mysql -<span style="color: #000000;">u rootWelcome to the MySQL monitor.  Commands end with ; or \g.Your MySQL connection </span><span style="color: #0000ff;">id</span> is <span style="color: #800080;">2</span><span style="color: #000000;">Server version: </span><span style="color: #800080;">5.7</span>.<span style="color: #800080;">10</span> MySQL Community Server (GPL)</pre></div><p>&nbsp;</p><p>查看一下user表，错误的起因就是在这里， root的plugin被修改成了auth_socket，用密码登陆的plugin应该是mysql_native_password。</p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div><pre>mysql<span style="color: #808080;">&gt;</span> <span style="color: #0000ff;">select</span> <span style="color: #ff00ff;">user</span>, plugin <span style="color: #0000ff;">from</span> mysql.<span style="color: #ff00ff;">user</span><span style="color: #000000;">;</span><span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">---------+-----------------------+</span><span style="color: #808080;">|</span> <span style="color: #ff00ff;">user</span>      <span style="color: #808080;">|</span> plugin                <span style="color: #808080;">|</span><span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">---------+-----------------------+</span><span style="color: #808080;">|</span> root      <span style="color: #808080;">|</span> auth_socket           <span style="color: #808080;">|</span><span style="color: #808080;">|</span> mysql.sys <span style="color: #808080;">|</span> mysql_native_password <span style="color: #808080;">|</span><span style="color: #808080;">|</span> dev       <span style="color: #808080;">|</span> mysql_native_password <span style="color: #808080;">|</span><span style="color: #808080;">+</span><span style="color: #008080;">--</span><span style="color: #008080;">---------+-----------------------+</span><span style="color: #800000; font-weight: bold;">3</span> rows <span style="color: #808080;">in</span> <span style="color: #0000ff;">set</span> (<span style="color: #800000; font-weight: bold;">0.01</span> sec)</pre><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div></div><p>&nbsp;</p><p>关于auth_socket，在官方有说明：&nbsp;<a href="https://dev.mysql.com/doc/mysql-security-excerpt/5.5/en/socket-authentication-plugin.html" target="_blank">https://dev.mysql.com/doc/mysql-security-excerpt/5.5/en/socket-authentication-plugin.html</a>&nbsp;，反正现在暂时不用它， 那就把这里改了。</p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div><pre>mysql<span style="color: #808080;">&gt;</span> <span style="color: #0000ff;">update</span> mysql.<span style="color: #ff00ff;">user</span> <span style="color: #0000ff;">set</span> authentication_string<span style="color: #808080;">=</span>PASSWORD(<span style="color: #ff0000;">'</span><span style="color: #ff0000;">newPwd</span><span style="color: #ff0000;">'</span>), plugin<span style="color: #808080;">=</span><span style="color: #ff0000;">'</span><span style="color: #ff0000;">mysql_native_password</span><span style="color: #ff0000;">'</span> <span style="color: #0000ff;">where</span> <span style="color: #ff00ff;">user</span><span style="color: #808080;">=</span><span style="color: #ff0000;">'</span><span style="color: #ff0000;">root</span><span style="color: #ff0000;">'</span><span style="color: #000000;">;Query OK, </span><span style="color: #800000; font-weight: bold;">1</span> row affected, <span style="color: #800000; font-weight: bold;">1</span> warning (<span style="color: #800000; font-weight: bold;">0.00</span><span style="color: #000000;"> sec)Rows matched: </span><span style="color: #800000; font-weight: bold;">1</span>  Changed: <span style="color: #800000; font-weight: bold;">1</span>  Warnings: <span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;"><p>mysql</span><span style="color: #808080;">&gt;</span> flush <span style="color: #0000ff;">privileges</span><span style="color: #000000;">;<br>Query OK, </span><span style="color: #800000; font-weight: bold;">0</span> rows affected (<span style="color: #800000; font-weight: bold;">0.00</span> sec)</pre></p><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div></div><p>&nbsp;</p><h3>重启服务，问题就解决了</h3><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div><pre>~$ <span style="color: #0000ff;">sudo</span><span style="color: #000000;"> service mysql stop... </span>* MySQL Community Server <span style="color: #800080;">5.7</span>.<span style="color: #800080;">10</span><span style="color: #000000;"> is stopped</span>~$ <span style="color: #0000ff;">sudo</span><span style="color: #000000;"> service mysql start.. </span>* MySQL Community Server <span style="color: #800080;">5.7</span>.<span style="color: #800080;">10</span><span style="color: #000000;"> is started</span>~$ mysql -u root -<span style="color: #000000;">pEnter password: Welcome to the MySQL monitor.  Commands end with ; or \g.Your MySQL connection </span><span style="color: #0000ff;">id</span> is <span style="color: #800080;">2</span><span style="color: #000000;">Server version: </span><span style="color: #800080;">5.7</span>.<span style="color: #800080;">10</span> MySQL Community Server (GPL)</pre><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div></div><p>&nbsp;</p><p>　　　　</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Django/Flask/Tornado三大web框架性能分析</title>
      <link href="python/flask/django-flask-tornado/"/>
      <url>python/flask/django-flask-tornado/</url>
      
        <content type="html"><![CDATA[<div class="rich_media_content"><p><span style="color:inherit;font-size:inherit;font-weight:bold;letter-spacing:0px;">写在前面：</span><br></p><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">本文的数据涉及到之前遇到过的问题，大概一次 http 请求到收到响应需要多少时间。这个问题在实际工作中与框架有比较大的关系，因此特别就框架的性能做了一次分析。</p><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">这里使用之前的一个报告数据： Python's Web Framework Benchmarks。本文仅关注目前最常用的三大 Python 框架：Django、 Flask 以及 Tornado。</p><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">报告主要比较三点：</p><ul style="font-size:inherit;color:inherit;line-height:inherit;padding-left:32px;" class="list-paddingleft-2"><li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">JSON：序列化一个对象，并返回一个 json。</span></p></li><li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">远程性能：从远程服务器上返回 http response 的时间</span></p></li><li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">数据库性能：使用 ORM（对象关系映射）从数据库获取数据，并渲染到模板上的时间</span></p></li></ul><h2 style="color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;font-weight:bold;font-size:1.4em;"><span style="font-size:inherit;color:inherit;line-height:inherit;"></span></h2><h2 style="color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;font-weight:bold;font-size:1.4em;"><a name="t1"></a>最基本的 json 测试：Django 与 Flask 占优<br><span style="font-size:inherit;color:inherit;line-height:inherit;"></span></h2><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">单纯在本地测试 json 的序列化，Django 完成一次 json 序列化的平均时间 42.52 毫秒，每秒请求量 4762 次。Flask 在此项测试中，与 Django 的比较不相上下，Flask 平均时间 43.33 毫秒，每秒请求量 4630 次。Tornado 完成 json 序列化的平均时间高达 77.51 毫秒，是所有框架中耗时最长的，每秒请求数是 2578 次，也是低于 Django 与 Flask 的水准。这仅仅说明框架在本地处理 json 的速度。框架还涉及 http request/response 以及数据库的读写，后面还需要综合来分析框架的性能。<br></p><img style="font-size:inherit;color:inherit;width:auto;height:auto;" title="" src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_png/yydwmWODxwPM1urP1Rgg2OdEbq6pjcC6LJ8fbBEAhlurP7Bibtu6h7dpymdZgWFy7nOP3ibcvsOguKzZc8UqE8gQ/640?wx_fmt=png" alt="640?wx_fmt=png"><br><img style="font-size:inherit;color:inherit;width:auto;height:auto;" title="" src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_png/yydwmWODxwPM1urP1Rgg2OdEbq6pjcC6kic774XBooZUbeuX391heYsW9fqmibsLRSvTlUWn9tiaaVXBPAya8zV0Q/640?wx_fmt=png" alt="640?wx_fmt=png"><h2 style="color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;font-weight:bold;font-size:1.4em;"><a name="t2"></a><span style="font-size:inherit;color:inherit;line-height:inherit;">处理远程 http 请求的能力：Tornado 占绝对优势</span></h2><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">从这项测试开始，Tornado 的强悍开始显现。Tornado 完成 http 请求的平均时间是 1.04 秒，而 Flask 是 3.34 秒，Django 是 3.48 秒，http 响应速度 Tornado 比 Flask 以及 Django 快三倍。</p><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">值得注意是，如果综合考虑 http 相应速度以及json 处理速度，如果把两项指标的平均时间相加：Tornado 耗时 1114.48 毫秒，Flask 是 3387.60 毫秒，Django 是 3519.88 毫秒。</p><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">Tornado 的好成绩得益于其自带的异步特性，而 Django 与 Flask 是同步框架，在处理请求时性能受限。但是实际使用中，一般是Django/Flask + Celery + Redis/Memchaned/RabbitMQ 的模式，由此带上了异步处理的能力。<br></p><img style="font-size:inherit;color:inherit;width:auto;height:auto;" title="" src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_png/yydwmWODxwPM1urP1Rgg2OdEbq6pjcC640K5rsnBUNC4kn2AkTT7wXqGCGryo1ibMuYNPesu2lBJHWQ9N20xsdg/640?wx_fmt=png" alt="640?wx_fmt=png"><br><img style="font-size:inherit;color:inherit;width:auto;height:auto;" title="" src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_png/yydwmWODxwPM1urP1Rgg2OdEbq6pjcC6wJAaibXexbsCgpaaXTNQsHZoxOLYDw5biaH3ibGqfeMpibzoiaJwg2b2eXQ/640?wx_fmt=png" alt="640?wx_fmt=png"><h2 style="color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;font-weight:bold;font-size:1.4em;"><a name="t3"></a><span style="font-size:inherit;color:inherit;line-height:inherit;">数据库与模板处理性能：Tornado 与 Flask 旗鼓相当</span></h2><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">Django 饱受诟病的地方就是 Django ORM 确实很慢，加上模板处理时间，Django 的平均时间 2904.04 毫秒，每秒处理请求量 42.9 次。然而 Django 的大部分功能是建立在其 Django ORM 基础上，比如 models, admin, forms 甚至第三方框架 django-rest-framework。Django 的开发效率与维护非常棒，然而 Django ORM 深度绑定了该框架，如果你需要把 Django ORM 换成其它轮子，那么也意味着 Django 的诸多优秀特性将从此告别。</p><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">Flask 事实上的 ORM 是 SQLAlchemy，SQLAlchemy 比 MySQLdb 的耗时多 5% 左右，所以是性能相当不错的数据库 ORM。得益于 SQLAlchemy 的优异性能，Flask 的每秒处理请求数为 123 次，平均处理时间 1440.24 秒，与 Tornado 性能相当。</p><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">Tornado 的每秒处理请求数为 143 次，平均处理时间 1344.69 秒。对于数据库与模板的处理，Tornado 与 Flask 不相上下。<br></p><img style="font-size:inherit;color:inherit;width:auto;height:auto;" title="" src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_png/yydwmWODxwPM1urP1Rgg2OdEbq6pjcC61nKBeqXKBOia9NpMZicYxNeDKnITvB7icHWSfZkibaA3o12ricXs0go1IMQ/640?wx_fmt=png" alt="640?wx_fmt=png"><br><img style="font-size:inherit;color:inherit;width:auto;height:auto;" title="" src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_jpg/yydwmWODxwPM1urP1Rgg2OdEbq6pjcC6NUcZLrLQ8WGvY1fciburIbmmTlA6h8SN9ckRic7BCCE4ibktHrewicxhfw/640?wx_fmt=jpeg" alt="640?wx_fmt=jpeg"><h2 style="color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;font-weight:bold;font-size:1.4em;"><a name="t4"></a><span style="font-size:inherit;color:inherit;line-height:inherit;">结论</span></h2><ul style="font-size:inherit;color:inherit;line-height:inherit;padding-left:32px;" class="list-paddingleft-2"><li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">Django：Python 界最全能的 web 开发框架，battery-include 各种功能完备，可维护性和开发速度一级棒。常有人说 Django 慢，其实主要慢在 Django ORM 与数据库的交互上，所以是否选用 Django，取决于项目对数据库交互的要求以及各种优化。而对于 Django 的同步特性导致吞吐量小的问题，其实可以通过 Celery 等解决，倒不是一个根本问题。Django 的项目代表：Instagram，Guardian。</span></p></li><li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">Tornado：天生异步，性能强悍是 Tornado 的名片，然而 Tornado 相比 Django 是较为原始的框架，诸多内容需要自己去处理。当然，随着项目越来越大，框架能够提供的功能占比越来越小，更多的内容需要团队自己去实现，而大项目往往需要性能的保证，这时候 Tornado 就是比较好的选择。Tornado项目代表：知乎。</span></p></li><li><p><span style="font-size:inherit;color:inherit;line-height:inherit;">Flask：微框架的典范，号称 Python 代码写得最好的项目之一。Flask 的灵活性，也是双刃剑：能用好 Flask 的，可以做成 Pinterest，用不好就是灾难（显然对任何框架都是这样）。Flask 虽然是微框架，但是也可以做成规模化的 Flask。加上 Flask 可以自由选择自己的数据库交互组件（通常是 Flask-SQLAlchemy），而且加上 celery +redis 等异步特性以后，Flask 的性能相对 Tornado 也不逞多让，也许Flask 的灵活性可能是某些团队更需要的。</span></p></li></ul><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;">总结，萝卜白菜各有所爱，然而机器的效率（程序的性能）与程序员的效率（可维护性、开发速度）是一对矛盾。选择什么样的架构组合，取决于产品的特性以及团队的能力。</p><p style="margin:5px 8px 16px;min-height:26px;white-space:normal;color:rgb(79,79,79);line-height:1.75em;text-align:center;"><span style="letter-spacing:.5px;font-size:15px;color:rgb(51,102,255);">∞</span><span style="letter-spacing:.5px;font-size:15px;color:rgb(153,153,153);">∞∞∞</span><span style="letter-spacing:.5px;font-size:15px;color:rgb(255,153,0);">∞</span></p><p style="white-space:normal;"><br></p><p style="white-space:normal;"><br></p><p></p><p style="text-align:center;"><img style="width:auto;height:auto;" title="undefined" width="75" src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_jpg/iae21LgCEd89muk21Gzate8ibt3tReZKiaxWQZPELq9umf8ZuPRYZWhTV6Ew7NfzZfKtBjDn4dtAMeSnubZHap1ng/640?wx_fmt=jpeg&amp;wx_lazy=1" alt="640?wx_fmt=jpeg&amp;wx_lazy=1"></p><span style="font-size:15px;">IT派 - {技术青年圈}</span><span style="color:rgb(165,165,165);font-size:10px;">持续关注互联网、区块链、人工智能领域</span><img style="width:auto;height:auto;" title="undefined" src= "/img/loading.gif" data-lazy-src="https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_jpg/iae21LgCEd8icPBAxIVOgsibDFMsI4Q1ibMaTAF55RdDEDlMHKgyiaetmibYs2iceDxYHpRH7wibYJgSL6m0yYyBficStZQ/640?wx_fmt=jpeg&amp;wx_lazy=1" alt="640?wx_fmt=jpeg&amp;wx_lazy=1"><p></p><p style="white-space:normal;"><br></p><p style="margin-right:8px;margin-left:8px;white-space:normal;text-align:center;line-height:1.75em;"><span style="font-size:18px;letter-spacing:.5px;color:rgb(51,51,51);"><br></span></p><p style="margin-right:8px;margin-left:8px;white-space:normal;text-align:center;line-height:1.75em;"><span style="font-size:18px;letter-spacing:.5px;color:rgb(51,51,51);">公众号回复</span><span style="font-size:18px;letter-spacing:.5px;color:rgb(54,65,173);">“机器学习”</span><span style="font-size:18px;letter-spacing:.5px;color:rgb(51,51,51);">，</span></p><p style="margin-right:8px;margin-left:8px;white-space:normal;text-align:center;line-height:1.75em;"><span style="font-size:18px;"><span style="letter-spacing:.5px;color:rgb(51,51,51);">邀你加入</span></span><span style="font-size:18px;color:rgb(255,153,0);letter-spacing:.5px;">{ IT派AI机器学习群 }&nbsp;</span></p><p style="font-size:inherit;color:inherit;line-height:inherit;margin-top:1.5em;margin-bottom:1.5em;"><br></p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> web </tag>
            
            <tag> django </tag>
            
            <tag> flask </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PHP MySQL 连接数据库</title>
      <link href="database/mysql/php/php-mysql-connect-database/"/>
      <url>database/mysql/php/php-mysql-connect-database/</url>
      
        <content type="html"><![CDATA[<div><h2>连接到一个 MySQL 数据库</h2><p>在您能够访问并处理数据库中的数据之前，您必须创建到达数据库的连接。</p><p>在 PHP 中，这个任务通过 mysql_connect() 函数完成。</p><h3>语法</h3><pre>mysql_connect(servername,username,password);</pre><table class="dataintable"><tbody><tr><th>参数</th><th>描述</th></tr><tr><td>servername</td><td>可选。规定要连接的服务器。默认是 "localhost:3306"。</td></tr><tr><td>username</td><td>可选。规定登录所使用的用户名。默认值是拥有服务器进程的用户的名称。</td></tr><tr><td>password</td><td>可选。规定登录所用的密码。默认是 ""。</td></tr></tbody></table><p class="note"><span>注释：</span>虽然还存在其他的参数，但上面列出了最重要的参数。请访问 W3School 提供的 <a href="/php/php_ref_mysql.asp" title="PHP MySQL 函数">PHP MySQL 参考手册</a>，获得更多的细节信息。</p><h3>例子</h3><p>在下面的例子中，我们在一个变量中 ($con) 存放了在脚本中供稍后使用的连接。如果连接失败，将执行 "die" 部分：</p><pre>&lt;?php$con = mysql_connect("localhost","peter","abc123");if (!$con)  {  die('Could not connect: ' . mysql_error());  }// some code?&gt;</pre></div><div><h2>关闭连接</h2><p>脚本一结束，就会关闭连接。如需提前关闭连接，请使用 mysql_close() 函数。</p><pre>&lt;?php$con = mysql_connect("localhost","peter","abc123");if (!$con)  {  die('Could not connect: ' . mysql_error());  }// some codemysql_close($con);?&gt;</pre></div><h3 id="相关推荐"><a href="#相关推荐" class="headerlink" title="相关推荐"></a>相关推荐</h3><p><a href="https://victorfengming.gitee.io/blog/php-mysql-connect-database/">PHP MySQL 连接数据库</a></p><p><a href="https://victorfengming.gitee.io/blog/php-mysql-insert/">PHP MySQL Insert Into</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> php </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PHP MySQL 创建数据库和表</title>
      <link href="database/mysql/php/php-mysql-createtables/"/>
      <url>database/mysql/php/php-mysql-createtables/</url>
      
        <content type="html"><![CDATA[<div id="maincontent"><div id="intro"><p><strong>数据库存有一个或多个表。</strong></p></div><div><h2>创建数据库</h2><p>CREATE DATABASE 语句用于在 MySQL 中创建数据库。</p><h3>语法</h3><pre>CREATE DATABASE database_name</pre><p>为了让 PHP 执行上面的语句，我们必须使用 mysql_query() 函数。此函数用于向 MySQL 连接发送查询或命令。</p><h3>例子</h3><p>在下面的例子中，我们创建了一个名为 "my_db" 的数据库：</p><pre>&lt;?php$con = mysql_connect("localhost","peter","abc123");if (!$con)  {  die('Could not connect: ' . mysql_error());  }if (mysql_query("CREATE DATABASE my_db",$con))  {  echo "Database created";  }else  {  echo "Error creating database: " . mysql_error();  }mysql_close($con);?&gt;</pre></div><div><h2>创建表</h2><p>CREATE TABLE 用于在 MySQL 中创建数据库表。</p><h3>语法</h3><pre>CREATE TABLE table_name(column_name1 data_type,column_name2 data_type,column_name3 data_type,.......)</pre><p>为了执行此命令，我必须向 mysql_query() 函数添加 CREATE TABLE 语句。</p><h3>例子</h3><p>下面的例子展示了如何创建一个名为 "Persons" 的表，此表有三列。列名是 "FirstName", "LastName" 以及 "Age"：</p><pre>&lt;?php$con = mysql_connect("localhost","peter","abc123");if (!$con)  {  die('Could not connect: ' . mysql_error());  }// Create databaseif (mysql_query("CREATE DATABASE my_db",$con))  {  echo "Database created";  }else  {  echo "Error creating database: " . mysql_error();  }// Create table in my_db databasemysql_select_db("my_db", $con);$sql = "CREATE TABLE Persons&nbsp;(FirstName varchar(15),LastName varchar(15),Age int)";mysql_query($sql,$con);mysql_close($con);?&gt;</pre><p class="important"><span>重要事项：</span>在创建表之前，必须首先选择数据库。通过 mysql_select_db() 函数选取数据库。</p><p class="note"><span>注释：</span>当您创建 varchar 类型的数据库字段时，必须规定该字段的最大长度，例如：varchar(15)。</p></div><div><h2>MySQL 数据类型</h2><p>下面的可使用的各种 MySQL 数据类型：</p><table class="dataintable"><tbody><tr><th style="width:40%">数值类型</th><th>描述</th></tr><tr><td><ul><li>int(size)</li><li>smallint(size)</li><li>tinyint(size)</li><li>mediumint(size)</li><li>bigint(size)</li></ul></td><td>仅支持整数。在 size 参数中规定数字的最大值。</td></tr><tr><td><ul><li>decimal(size,d)</li><li>double(size,d)</li><li>float(size,d)</li></ul></td><td><p>支持带有小数的数字。</p><p>在 size 参数中规定数字的最大值。在 d 参数中规定小数点右侧的数字的最大值。</p></td></tr></tbody></table><table class="dataintable"><tbody><tr><th style="width:40%">文本数据类型</th><th>描述</th></tr><tr><td>char(size)</td><td><p>支持固定长度的字符串。（可包含字母、数字以及特殊符号）。</p><p>在 size 参数中规定固定长度。</p></td></tr><tr><td>varchar(size)</td><td><p>支持可变长度的字符串。（可包含字母、数字以及特殊符号）。</p><p>在 size 参数中规定最大长度。</p></td></tr><tr><td>tinytext</td><td>支持可变长度的字符串，最大长度是 255 个字符。</td></tr><tr><td><ul><li>text</li><li>blob</li></ul></td><td>支持可变长度的字符串，最大长度是 65535 个字符。</td></tr><tr><td><ul><li>mediumtext</li><li>mediumblob</li></ul></td><td>支持可变长度的字符串，最大长度是 16777215 个字符。</td></tr><tr><td><ul><li>longtext</li><li>longblob</li></ul></td><td>支持可变长度的字符串，最大长度是 4294967295 个字符。</td></tr></tbody></table><table class="dataintable"><tbody><tr><th style="width:40%">日期数据类型</th><th>描述</th></tr><tr><td><ul><li>date(yyyy-mm-dd)</li><li>datetime(yyyy-mm-dd hh:mm:ss)</li><li>timestamp(yyyymmddhhmmss)</li><li>time(hh:mm:ss)</li></ul></td><td>支持日期或时间</td></tr></tbody></table><table class="dataintable"><tbody><tr><th style="width:40%">杂项数据类型</th><th>描述</th></tr><tr><td>enum(value1,value2,ect)</td><td>ENUM 是 ENUMERATED 列表的缩写。可以在括号中存放最多 65535 个值。</td></tr><tr><td>set</td><td>SET 与 ENUM 相似。但是，SET 可拥有最多 64 个列表项目，并可存放不止一个 choice</td></tr></tbody></table></div><div><h2>主键和自动递增字段</h2><p>每个表都应有一个主键字段。</p><p>主键用于对表中的行进行唯一标识。每个主键值在表中必须是唯一的。此外，主键字段不能为空，这是由于数据库引擎需要一个值来对记录进行定位。</p><p>主键字段永远要被编入索引。这条规则没有例外。你必须对主键字段进行索引，这样数据库引擎才能快速定位给予该键值的行。</p><p>下面的例子把 personID 字段设置为主键字段。主键字段通常是 ID 号，且通常使用 AUTO_INCREMENT 设置。AUTO_INCREMENT 会在新记录被添加时逐一增加该字段的值。要确保主键字段不为空，我们必须向该字段添加 NOT NULL 设置。</p><h3>例子</h3><pre>$sql = "CREATE TABLE Persons&nbsp;(personID int NOT NULL AUTO_INCREMENT, PRIMARY KEY(personID),FirstName varchar(15),LastName varchar(15),Age int)";<p>mysql_query($sql,$con);</pre></p></div><div id="bpn"><ul class="prenext"><li class="pre"><a href="/php/php_mysql_connect.asp" title="PHP MySQL 连接数据库">MySQL Connect</a></li><li class="next"><a href="/php/php_mysql_insert.asp" title="PHP MySQL Insert Into">MySQL Insert</a></li></ul></div></div><h3 id="相关推荐"><a href="#相关推荐" class="headerlink" title="相关推荐"></a>相关推荐</h3><p><a href="https://victorfengming.gitee.io/blog/php-mysql-connect-database/">PHP MySQL 连接数据库</a></p><p><a href="https://victorfengming.gitee.io/blog/php-mysql-insert/">PHP MySQL Insert Into</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> php </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PHP MySQL Insert Into</title>
      <link href="database/mysql/php/php-mysql-insert/"/>
      <url>database/mysql/php/php-mysql-insert/</url>
      
        <content type="html"><![CDATA[<div id="maincontent"><div id="intro"><p><strong>INSERT INTO 语句用于向数据库表中插入新记录。</strong></p></div><div><h2>向数据库表插入数据</h2><p>INSERT INTO 语句用于向数据库表添加新记录。</p><h3>语法</h3><pre>INSERT INTO table_nameVALUES (value1, value2,....)</pre><p>您还可以规定希望在其中插入数据的列：</p><pre>INSERT INTO table_name (column1, column2,...)VALUES (value1, value2,....)</pre><p class="note"><span>注释：</span>SQL 语句对大小写不敏感。INSERT INTO 与 insert into 相同。</p><p>为了让 PHP 执行该语句，我们必须使用 mysql_query() 函数。该函数用于向 MySQL 连接发送查询或命令。</p><h3>例子</h3><p>在前面的章节，我们创建了一个名为 "Persons" 的表，有三个列："Firstname", "Lastname" 以及 "Age"。我们将在本例中使用同样的表。下面的例子向 "Persons" 表添加了两个新记录：</p><pre>&lt;?php$con = mysql_connect("localhost","peter","abc123");if (!$con)  {  die('Could not connect: ' . mysql_error());  }mysql_select_db("my_db", $con);mysql_query("INSERT INTO Persons (FirstName, LastName, Age) VALUES ('Peter', 'Griffin', '35')");mysql_query("INSERT INTO Persons (FirstName, LastName, Age) VALUES ('Glenn', 'Quagmire', '33')");mysql_close($con);?&gt;</pre></div><div><h2>把来自表单的数据插入数据库</h2><p>现在，我们创建一个 HTML 表单，这个表单可把新记录插入 "Persons" 表。</p><p>这是这个 HTML 表单：</p><pre>&lt;html&gt;&lt;body&gt;&lt;form action="insert.php" method="post"&gt;Firstname: &lt;input type="text" name="firstname" /&gt;Lastname: &lt;input type="text" name="lastname" /&gt;Age: &lt;input type="text" name="age" /&gt;&lt;input type="submit" /&gt;&lt;/form&gt;&lt;/body&gt;&lt;/html&gt;</pre><p>当用户点击上例中 HTML 表单中的提交按钮时，表单数据被发送到 "insert.php"。"insert.php" 文件连接数据库，并通过 $_POST 变量从表单取回值。然后，mysql_query() 函数执行 INSERT INTO 语句，一条新的记录会添加到数据库表中。</p><p>下面是 "insert.php" 页面的代码：</p><pre>&lt;?php$con = mysql_connect("localhost","peter","abc123");if (!$con)  {  die('Could not connect: ' . mysql_error());  }mysql_select_db("my_db", $con);$sql="INSERT INTO Persons (FirstName, LastName, Age)VALUES('$_POST[firstname]','$_POST[lastname]','$_POST[age]')";if (!mysql_query($sql,$con))  {  die('Error: ' . mysql_error());  }echo "1 record added";mysql_close($con)?&gt;</pre></div><div id="bpn"><ul class="prenext"><li class="pre"><a href="/php/php_mysql_create.asp" title="PHP MySQL 创建数据库和表">MySQL Create</a></li><li class="next"><a href="/php/php_mysql_select.asp" title="PHP MySQL Select">MySQL Select</a></li></ul></div></div><h3 id="相关推荐"><a href="#相关推荐" class="headerlink" title="相关推荐"></a>相关推荐</h3><p><a href="https://victorfengming.gitee.io/blog/php-mysql-connect-database/">PHP MySQL 连接数据库</a></p><p><a href="https://victorfengming.gitee.io/blog/php-mysql-createtables/">PHP MySQL 创建数据库和表</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> php </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MariaDB mysql 比较区别选择</title>
      <link href="database/diff-mysql-mariadb/"/>
      <url>database/diff-mysql-mariadb/</url>
      
        <content type="html"><![CDATA[<p> MariaDB<br> 数据库管理系统是<br> MySQL<br> 的一个分支</p><p> 开发这个分支的原因之一是：<br> 甲骨文公司<br> 收购了MySQL后，有将MySQL<br> 闭源<br> 的潜在风险，因此社区采用分支的方式来避开这个风险。</p><p> MariaDB的目的是完全兼容MySQL，包括<br> API<br> 和命令行，使之能轻松成为MySQL的代替品。在存储引擎方面，10.0.9版起使用<br> XtraDB<br> （名称代号为<br> Aria<br> ）来代替MySQL的<br> InnoDB<br> 。</p><p> MariaDB直到5.5版本，均依照MySQL的版本。因此，使用MariaDB5.5的人会从MySQL 5.5中了解到MariaDB的所有功能。</p><p> 从2012年11月12日起发布的10.0.0版开始，不再依照MySQL的版号。10.0.x版以5.5版为基础，加上移植自MySQL 5.6版的功能和自行开发的新功能。</p><p> MySQL分支的选择：Percona还是MariaDB</p><p> PostgreSQL一直被当作MySQL的直接竞争对手</p><p> MyISAM没有提供事务支持，而InnoDB提供了事务支持。</p><p> XtraDB 是 InnoDB 存储引擎的增强版</p><p> 谷歌和维基都选择了mariaDB</p><p> MariaDB是MySQL创始人搞的</p><p> PostgreSQL 与 MySQL 相比，优势何在？</p><p> 不少人应该遇到过 MySQL 里需要 utf8mb4 才能显示 emoji 的坑, Pg 就没这个坑</p><p> <a href="https://www.zhihu.com/question/20010554">https://www.zhihu.com/question/20010554</a></p><p> <a href="https://db-engines.com/en/system/MariaDB%3BPostgreSQL">https://db-engines.com/en/system/MariaDB%3BPostgreSQL</a></p><p> <a href="http://www.infoq.com/cn/news/2013/12/mysql-vs-postgresql">http://www.infoq.com/cn/news/2013/12/mysql-vs-postgresql</a></p><p>原文链接：<a href="https://blog.csdn.net/elesos/article/details/73804680">https://blog.csdn.net/elesos/article/details/73804680</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> Linux </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>mysql中的内置函数</title>
      <link href="database/mysql/mysql-inner-function/"/>
      <url>database/mysql/mysql-inner-function/</url>
      
        <content type="html"><![CDATA[<div id="cnblogs_post_body" class="blogpost-body cnblogs-markdown">    <p>mysql内置函数列表可以从<a href="http://dev.mysql.com/doc/refman/5.6/en/func-op-summary-ref.html">mysql官方文档</a>查询，这里仅分类简单介绍一些可能会用到的函数。</p><h3 id="数学函数">1 数学函数</h3><p>abs(x)<br>pi()<br>mod(x,y)<br>sqrt(x)<br>ceil(x)或者ceiling(x)<br>rand(),rand(N):返回0-1间的浮点数，使用不同的seed N可以获得不同的随机数<br>round(x, D)：四舍五入保留D位小数，D默认为0， 可以为负数， 如round(19, -1)返回20<br>truncate(x, D):截断至保留D位小数，D可以为负数， 如trancate(19,-1)返回10<br>sign(x): 返回x的符号，正负零分别返回1， -1， 0<br>pow(x,y)或者power(x,y)<br>exp(x)：e^x<br>log(x)：自然对数<br>log10(x)：以10为底的对数<br>radians(x):角度换弧度<br>degrees(x):弧度换角度<br>sin(x)和asin(x):<br>cos(x)和acos(x):<br>tan(x)和atan(x):<br>cot(x):</p><h3 id="字符串函数">2 字符串函数</h3><p>char_length(str):返回str所包含的字符数，一个多字节字符算一个字符<br>length(str): 返回字符串的字节长度，如utf8中，一个汉字3字节，数字和字母算一个字节<br>concat(s1, s1, ...): 返回连接参数产生的字符串<br>concat_ws(x, s1, s2, ...): 使用连接符x连接其他参数产生的字符串<br>INSERT(str,pos,len,newstr):返回str,其起始于pos，长度为len的子串被newstr取代。<br>1. 若pos不在str范围内，则返回原字符串str<br>2. 若str中从pos开始的子串不足len,则将从pos开始的剩余字符用newstr取代<br>3. 计算pos时从1开始，若pos=3,则从第3个字符开始替换<br>lower（str)或者lcase(str):<br>upper(str)或者ucase(str):<br>left(s,n):返回字符串s最左边n个字符<br>right(s,n): 返回字符串最右边n个字符<br>lpad(s1, len, s2): 用s2在s1左边填充至长度为len, 若s1的长度大于len,则截断字符串s1至长度len返回<br>rpad(s1, len, s2):<br>ltrim(s):删除s左侧空格字符<br>rtrim(s):<br>TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str)或TRIM([remstr FROM] str)：从str中删除remstr, remstr默认为空白字符<br>REPEAT(str,count)：返回str重复count次得到的新字符串<br>REPLACE(str,from_str,to_str)： 将str中的from_str全部替换成to_str<br>SPACE(N):返回长度为N的空白字符串<br>STRCMP(str1,str2):若str1和str2相同，返回0， 若str1小于str2, 返回-1， 否则返回1.<br>SUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len), SUBSTRING(str FROM pos FOR len),MID(str,pos,len): 获取特定位置，特定长度的子字符串<br>LOCATE(substr,str), LOCATE(substr,str,pos),INSTR(str,substr),POSITION(substr IN str): 返回字符串中特定子串的位置，注意这里INSTR与其他函数的参数位置是相反的<br>REVERSE(str)<br>ELT(N,str1,str2,str3,...)：返回参数strN, 若N大于str参数个数，则返回NULL<br>FIELD(str,str1,str2,str3,...): 返回str在后面的str列表中第一次出现的位置，若找不到str或者str为NULL, 则返回0<br>FIND_IN_SET(str,strlist)：strlist是由','分隔的字符串，若str不在strlist或者strlist为空字符串，则返回0；若任意一个参数为NULL则返回ＮＵＬＬ<br>MAKE_SET(bits,str1,str2,...): 由bits的作为位图来选取strN参数，选中的参数用','连接后返回</p><h3 id="日期和时间函数">3 日期和时间函数</h3><p>CURDATE(), CURRENT_DATE, CURRENT_DATE():用于获取当前日期，格式为'YYYY-MM-DD'; 若+0则返回YYYYMMDD<br>UTC_DATE, UTC_DATE():返回当前世界标准时间<br>CURTIME([fsp]), CURRENT_TIME, CURRENT_TIME([fsp]): 用于获取当前时间， 格式为'HH:MM:SS' 若+0则返回 HHMMSS<br>UTC_TIME, UTC_TIME([fsp])<br>CURRENT_TIMESTAMP, CURRENT_TIMESTAMP([fsp]), LOCALTIME, LOCALTIME([fsp]), SYSDATE([fsp]), NOW([fsp]): 用于获取当前的时间日期，格式为'YYYY-MM-DD HH:MM:SS'，若+0则返回YYYYMMDDHHMMSS<br>UTC_TIMESTAMP, UTC_TIMESTAMP([fsp])<br>UNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)：返回一个unix时间戳（'1970-01-01 00:00:00' UTC至今或者date的秒数），这实际上是从字符串到整数的一个转化过程<br>FROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)：从时间戳返回'YYYY-MM-DD HH:MM:SS' 或者YYYYMMDDHHMMSS，加入format后根据所需的format显示。<br>MONTH(date)<br>MONTHNAME(date)<br>DAYNAME(date)<br>DAY(date)，DAYOFMONTH(date)：1-31或者0<br>DAYOFWEEK(date)：1-7==&gt;星期天-星期六<br>DAYOFYEAR(date)： 1-365（366）<br>WEEK(date[,mode])：判断是一年的第几周，如果1-1所在周在新的一年多于4天，则将其定为第一周；否则将其定为上一年的最后一周。mode是用来人为定义一周从星期几开始。<br>WEEKOFYEAR(date)：类似week(date,3)，从周一开始计算一周。<br>QUARTER(date)：返回1-4<br>HOUR(time)：返回时间中的小时数，可以大于24<br>MINUTE(time)：<br>SECOND(time)：<br>EXTRACT(unit FROM date)：提取日期时间中的要素</p><pre class="sql"><code class="hljs">    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">EXTRACT</span>(<span class="hljs-keyword">YEAR</span> <span class="hljs-keyword">FROM</span> <span class="hljs-string">'2009-07-02'</span>); ##2009    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">EXTRACT</span>(YEAR_MONTH <span class="hljs-keyword">FROM</span> <span class="hljs-string">'2009-07-02 01:02:03'</span>);##200907    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">EXTRACT</span>(DAY_MINUTE <span class="hljs-keyword">FROM</span> <span class="hljs-string">'2009-07-02 01:02:03'</span>);##20102    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">EXTRACT</span>(<span class="hljs-keyword">MICROSECOND</span> <span class="hljs-keyword">FROM</span> <span class="hljs-string">'2003-01-02 10:30:00.000123'</span>);##123</code></pre><p>TIME_TO_SEC(time)<br>SEC_TO_TIME(seconds)</p><p>TO_DAYS(date): 从第0年开始的天数<br>TO_SECNDS(expr)：从第0年开始的秒数</p><p>ADDDATE(date,INTERVAL expr unit), ADDDATE(expr,days),DATE_ADD(date,INTERVAL expr unit)<br>DATE_SUB(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)<br>ADDTIME(expr1,expr2)<br>SUBTIME(expr1,expr2)</p><pre class="sql"><code class="hljs">    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">ADDTIME</span>(<span class="hljs-string">'2007-12-31 23:59:59.999999'</span>, <span class="hljs-string">'1 1:1:1.000002'</span>);##'2008-01-02 01:01:01.000001'    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">ADDTIME</span>(<span class="hljs-string">'01:00:00.999999'</span>, <span class="hljs-string">'02:00:00.999998'</span>);##'03:00:01.999997'</code></pre><p>注意：时间日期的加减也可以直接用+/-来进行</p><pre class="sql"><code class="hljs">    date + INTERVAL expr unit    date - INTERVAL expr unit    如：    <span class="hljs-keyword">SELECT</span> <span class="hljs-string">'2008-12-31 23:59:59'</span> + <span class="hljs-built_in">INTERVAL</span> <span class="hljs-number">1</span> <span class="hljs-keyword">SECOND</span>;##'2009-01-01 00:00:00'    <span class="hljs-keyword">SELECT</span> <span class="hljs-built_in">INTERVAL</span> <span class="hljs-number">1</span> <span class="hljs-keyword">DAY</span> + <span class="hljs-string">'2008-12-31'</span>;##'2009-01-01'    <span class="hljs-keyword">SELECT</span> <span class="hljs-string">'2005-01-01'</span> - <span class="hljs-built_in">INTERVAL</span> <span class="hljs-number">1</span> <span class="hljs-keyword">SECOND</span>;##'2004-12-31 23:59:59'</code></pre><p>DATE_FORMAT(date,format):<br>DATEDIFF(expr1,expr2):返回相差的天数<br>TIMEDIFF(expr1,expr2)：返回相隔的时间</p><h3 id="条件判断函数">4 条件判断函数</h3><p>IF(expr1,expr2,expr3)：如果expr1不为0或者NULL,则返回expr2的值，否则返回expr3的值<br>IFNULL(expr1,expr2)：如果expr1不为NULL,返回expr1,否则返回expr2<br>NULLIF(expr1,expr2): 如果expr1=expr2则返回NULL, 否则返回expr2<br>CASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN result ...] [ELSE result] END<br>当compare_value=value时返回result<br>CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END<br>当condition为TRUE时返回result</p><pre class="sql"><code class="hljs">    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">CASE</span> <span class="hljs-number">1</span> <span class="hljs-keyword">WHEN</span> <span class="hljs-number">1</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'one'</span>        <span class="hljs-keyword">WHEN</span> <span class="hljs-number">2</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'two'</span> <span class="hljs-keyword">ELSE</span> <span class="hljs-string">'more'</span> <span class="hljs-keyword">END</span>;##'one'    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">CASE</span> <span class="hljs-keyword">WHEN</span> <span class="hljs-number">1</span>&gt;<span class="hljs-number">0</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'true'</span> <span class="hljs-keyword">ELSE</span> <span class="hljs-string">'false'</span> <span class="hljs-keyword">END</span>;##'true'    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">CASE</span> <span class="hljs-built_in">BINARY</span> <span class="hljs-string">'B'</span>        <span class="hljs-keyword">WHEN</span> <span class="hljs-string">'a'</span> <span class="hljs-keyword">THEN</span> <span class="hljs-number">1</span> <span class="hljs-keyword">WHEN</span> <span class="hljs-string">'b'</span> <span class="hljs-keyword">THEN</span> <span class="hljs-number">2</span> <span class="hljs-keyword">END</span>;##NULL</code></pre><h3 id="系统信息函数">5 系统信息函数</h3><p>VERSION():返回mysql服务器的版本，是utf8编码的字符串<br>CONNECTION_ID()：显示连接号（连接的线程号）<br>DATABASE()，SCHEMA()：显示当前使用的数据库<br>SESSION_USER(), SYSTEM_USER(), USER(), CURRENT_USER, CURRENT_USER():返回当前的用户名@主机，utf8编码字符串<br>CHARSET(str)<br>COLLATION(str)<br>LAST_INSERT_ID()：自动返回最后一个insert或者update查询， 为auto_increment列设置的第一个发生的值</p><h3 id="加密和压缩函数">6 加密和压缩函数</h3><p>PASSWORD(str):这个函数的输出与变量old_password有关。old_password 在mysql5.6中默认为0。 不同取值的效果如下表<br><img src= "/img/loading.gif" data-lazy-src="https://images2015.cnblogs.com/blog/865265/201602/865265-20160224150201724-1500361171.png"><br>old_password=1时， password(str)的效果与old_password(str)相同，由于其不够安全已经弃用（5.6.5以后）。<br>old_password=2时，在生成哈希密码时会随机加盐。</p><p>MD5(str):计算MD5 128位校验和，返回32位16进制数构成的字符串，当str为NULL时返回NULL。可以用作哈希密码<br>SHA1(str), SHA(str)：计算160位校验和，返回40位16进制数构成的字符串，当str为NULL时返回NULL。<br>SHA2(str, hash_length)：计算SHA-2系列的哈希方法(SHA-224, SHA-256, SHA-384, and SHA-512). 第一个参数为待校验字符串，第二个参数为结果的位数（224， 256， 384， 512）<br>ENCRYPT(str[,salt]): 用unix crypt()来加密str. salt至少要有两位字符，否则会返回NULL。若未指定salt参数，则会随机添加salt。</p><p>ECODE(crypt_str,pass_str):解密crypt_str, pass_str用作密码<br>ENCODE(str,pass_str)：用pass_str作为密码加密str</p><p>DES_ENCRYPT(str[,{key_num|key_str}])：用Triple-DES算法编码str， 这个函数只有在mysql配置成支持ssl时才可用。<br>DES_DECRYPT(crypt_str[,key_str])</p><p>AES_ENCRYPT(str,key_str[,init_vector])<br>AES_DECRYPT(crypt_str,key_str[,init_vector])</p><p>COMPRESS(string_to_compress)：返回二进制码<br>UNCOMPRESS(string_to_uncompress)</p><h3 id="聚合函数">7 聚合函数</h3><p>若在没使用group by时使用聚合函数，相当于把所有的行都归于一组来进行处理。除非特殊说明，一般聚合函数会忽略掉NULL.<br>AVG([DISTINCT] expr): 返回expr的平均值，distinct选项用于忽略重复值<br>COUNT([DISTINCT] expr)：返回select中expr的非0值个数，返回值为bigint类型<br>group_concat:连接组内的非空值，若无非空值，则返回NULL</p><pre class="sql"><code class="hljs">        GROUP_CONCAT([DISTINCT] expr [,expr ...]             [ORDER BY &#123;unsigned_integer | col_name | expr&#125;                    [ASC | DESC] [,col_name ...]]            [SEPARATOR str_val])</code></pre><p>MAX([DISTINCT] expr)<br>MIN([DISTINCT] expr)</p><p>SUM([DISTINCT] expr)<br>VAR_POP(expr)<br>VARIANCE(expr)：同VAR_POP(expr)，但是这是标准sql的一个扩展函数<br>VAR_SAMP(expr)<br>STD(expr): 这是标准sql的一个扩展函数<br>STDDEV(expr)：这个函数是为了跟oracle兼容而设置的<br>STDDEV_POP(expr)：这个是sql标准函数</p><p>STDDEV_SAMP(expr)：样本标准差</p><h3 id="格式或类型转化函数">8 格式或类型转化函数</h3><p>FORMAT(X,D[,locale])：将数字X转化成'#,###,###.##'格式，D为保留的小数位数<br>CONV(N,from_base,to_base)：改变数字N的进制，返回值为该进制下的数字构成的字符串<br>INET_ATON(expr)：ip字符串转数字<br>INET_NTOA(expr)：数字转ip字符串<br>CAST(expr AS type)：转换数据类型<br>CONVERT(expr,type), CONVERT(expr USING transcoding_name)： type可以为BINARY[(N)]，CHAR[(N)]，DATE，DATETIME， DECIMAL[(M[,D])]，DECIMAL[(M[,D])]，TIME，UNSIGNED [INTEGER]等等。transcoding_name如utf8等等</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> Linux </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>mysql中的RDBMS 术语</title>
      <link href="database/rdbms-terminology/"/>
      <url>database/rdbms-terminology/</url>
      
        <content type="html"><![CDATA[<h3 id="RDBMS即关系数据库管理系统-Relational-Database-Management-System-的特点："><a href="#RDBMS即关系数据库管理系统-Relational-Database-Management-System-的特点：" class="headerlink" title="RDBMS即关系数据库管理系统(Relational Database Management System)的特点："></a>RDBMS即关系数据库管理系统(Relational Database Management System)的特点：</h3><ol><li>数据以表格的形式出现</li><li>每行为各种记录名称</li><li>每列为记录名称所对应的数据域</li><li>许多的行和列组成一张表单</li><li>若干的表单组成database</li></ol><h3 id="RDBMS-术语"><a href="#RDBMS-术语" class="headerlink" title="RDBMS 术语"></a>RDBMS 术语</h3><p>在我们开始学习MySQL 数据库前，让我们先了解下RDBMS的一些术语：</p><ul><li>数据库: 数据库是一些关联表的集合。.</li><li>数据表: 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。</li><li>列: 一列(数据元素) 包含了相同的数据, 例如邮政编码的数据。</li><li>行：一行（=元组，或记录）是一组相关的数据，例如一条用户订阅的数据。</li><li>冗余：存储两倍数据，冗余可以使系统速度更快。</li><li>主键：主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。</li><li>外键：外键用于关联两个表。</li><li>复合键：复合键（组合键）将多个列作为一个索引键，一般用于复合索引。</li><li>索引：使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。类似于书籍的目录。</li><li>参照完整性: 参照的完整性要求关系中不允许引用不存在的实体。与实体完整性是关系模型必须满足的完整性约束条件，目的是保证数据的一致性。</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> Linux </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Oracle基础知识总结</title>
      <link href="database/oracle-knowledge/"/>
      <url>database/oracle-knowledge/</url>
      
        <content type="html"><![CDATA[<p>原文链接: <a href="https://blog.csdn.net/qq_39876666/article/details/82764040">https://blog.csdn.net/qq_39876666/article/details/82764040</a></p><h2 id="ORACLE-基础"><a href="#ORACLE-基础" class="headerlink" title="ORACLE 基础"></a>ORACLE 基础</h2><h3 id="ORACLE-数据库具有以下特点："><a href="#ORACLE-数据库具有以下特点：" class="headerlink" title="ORACLE 数据库具有以下特点："></a>ORACLE 数据库具有以下特点：</h3><ul><li>支持多用户、大事务量的事务处理</li><li>数据安全性和完整性控制</li><li>支持分布式数据处理</li><li>可移植性</li></ul><h3 id="ORACLE-体系结构"><a href="#ORACLE-体系结构" class="headerlink" title="ORACLE 体系结构"></a>ORACLE 体系结构</h3><ul><li>数据库</li><li>实例</li><li>数据文件(dbf)</li><li>表空间<ul><li>用户</li></ul></li></ul><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/2018091818142275?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5ODc2NjY2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="实力示意图"></p><h3 id="创建表空间"><a href="#创建表空间" class="headerlink" title="创建表空间"></a>创建表空间</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">create tablespace waterboss</span><br><span class="line">datafile &#39;c:\waterboss.dbf&#39;</span><br><span class="line">size 100m</span><br><span class="line">autoextend on</span><br><span class="line">next 10m</span><br><span class="line"></span><br><span class="line">waterboss 为表空间名称</span><br><span class="line">datafile 用于设置物理文件名称</span><br><span class="line">size 用于设置表空间的初始大小</span><br><span class="line">autoextend on 用于设置自动增长，如果存储量超过初始大小，则开始自动扩容</span><br><span class="line">next 用于设置扩容的空间大小</span><br></pre></td></tr></table></figure><h3 id="创建用户"><a href="#创建用户" class="headerlink" title="创建用户"></a>创建用户</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">create user wateruser</span><br><span class="line">identified by itcast</span><br><span class="line">default tablespace waterboss</span><br><span class="line"></span><br><span class="line">wateruser 为创建的用户名</span><br><span class="line">identified by 用于设置用户的密码</span><br><span class="line">default tablesapce 用于指定默认表空间名称</span><br></pre></td></tr></table></figure><h3 id="用户赋权"><a href="#用户赋权" class="headerlink" title="用户赋权"></a>用户赋权</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grant dba to wateruser</span><br></pre></td></tr></table></figure><h3 id="表的创建、修改与删除"><a href="#表的创建、修改与删除" class="headerlink" title="表的创建、修改与删除"></a>表的创建、修改与删除</h3><h4 id="创建表"><a href="#创建表" class="headerlink" title="创建表"></a>创建表</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE 表名称(</span><br><span class="line">字段名 类型(长度) primary key,</span><br><span class="line">字段名 类型(长度),</span><br><span class="line">.......</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h4 id="数据类型："><a href="#数据类型：" class="headerlink" title="数据类型："></a>数据类型：</h4><ul><li><p>字符型</p><ol start="0"><li>CHAR : 固定长度的字符类型，最多存储 2000 个字节</li><li>VARCHAR2 :可变长度的字符类型，最多存储 4000 个字节</li><li>LONG : 大文本类型。最大可以存储 2 个 G</li></ol></li><li><p>数值型</p><ol start="0"><li>NUMBER : 数值类型</li><li>例如：NUMBER(5) 最大可以存的数为 99999</li><li>NUMBER(5,2) 最大可以存的数为 999.99</li></ol></li><li><p>日期型</p><ol start="0"><li>DATE：日期时间型，精确到秒</li><li>TIMESTAMP：精确到秒的小数点后 9 位</li></ol></li><li><p>二进制型（大数据类型）</p><ol start="0"><li>CLOB : 存储字符,最大可以存 4 个 G</li><li>BLOB：存储图像、声音、视频等二进制数据,最多可以存 4 个 G</li></ol></li></ul><h4 id="修改表"><a href="#修改表" class="headerlink" title="修改表"></a>修改表</h4><ul><li>增加字段</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALTER TABLE 表名称 ADD(列名 1 类型 [DEFAULT 默认值]，列名 1 类型 [DEFAULT 默认值]…)</span><br></pre></td></tr></table></figure><ul><li>修改字段</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALTER TABLE 表名称 MODIFY(列名 1 类型 [DEFAULT 默认值]，列名 1 类型 [DEFAULT 默认值]…)</span><br></pre></td></tr></table></figure><ul><li>修改字段名</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALTER TABLE 表名称 RENAME COLUMN 原列名 TO 新列名</span><br></pre></td></tr></table></figure><ul><li>删除字段名</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALTER TABLE T_OWNERS DROP COLUMN REMARK</span><br></pre></td></tr></table></figure><h4 id="删除表"><a href="#删除表" class="headerlink" title="删除表"></a>删除表</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">drop table 表名称</span><br></pre></td></tr></table></figure><h3 id="数据增删改"><a href="#数据增删改" class="headerlink" title="数据增删改"></a>数据增删改</h3><ul><li>INSERT INTO 表名[(列名 1，列名 2，…)]VALUES(值 1，值2，…)</li><li>UPDATE 表名 SET 列名 1=值 1，列名 2=值 2，…WHERE 修改条件；</li><li>DELETE FROM 表名 WHERE 删除条件;</li><li>TRUNCATE TABLE 表名称 —- 删除表</li></ul><h4 id="比较-truncat-与-delete-实现数据删除？"><a href="#比较-truncat-与-delete-实现数据删除？" class="headerlink" title="比较 truncat 与 delete 实现数据删除？"></a>比较 truncat 与 delete 实现数据删除？</h4><ol start="0"><li>delete 删除的数据可以 rollback</li><li>delete 删除可能产生碎片，并且不释放空间</li><li>truncate 是先摧毁表结构，再重构表结构</li></ol><h4 id="JDBC-连接-ORACLE"><a href="#JDBC-连接-ORACLE" class="headerlink" title="JDBC 连接 ORACLE"></a>JDBC 连接 ORACLE</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//加载驱动</span></span><br><span class="line"><span class="keyword">static</span>&#123;</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">Class.forName(<span class="string">&quot;oracle.jdbc.driver.OracleDriver&quot;</span>);Class.forName(<span class="string">&quot;oracle.jdbc.driver.OracleDriver&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">catch</span> (ClassNotFoundException e) &#123;</span><br><span class="line">e.printStackTrace();e.printStackTrace();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取数据库连接</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> java.sql.<span class="function">Connection <span class="title">getConnection</span><span class="params">()</span> throwsSQLException</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> java.sql.DriverManager.getConnection(<span class="string">&quot;jdbc:oracle:thin:@192.168.80.10:1521:orcl&quot;</span>,<span class="string">&quot;wateruser&quot;</span>, <span class="string">&quot;itcast&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h5 id="JDBC-驱动为："><a href="#JDBC-驱动为：" class="headerlink" title="JDBC 驱动为："></a>JDBC 驱动为：</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">oracle.jdbc.OracleDriver</span><br></pre></td></tr></table></figure><h5 id="连接字符串-瘦连接-："><a href="#连接字符串-瘦连接-：" class="headerlink" title="连接字符串( 瘦连接 )："></a>连接字符串( 瘦连接 )：</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:oracle:thin:@虚拟机的 IP:1521:orcl</span><br></pre></td></tr></table></figure><h3 id="数据导出与导入"><a href="#数据导出与导入" class="headerlink" title="数据导出与导入"></a>数据导出与导入</h3><h4 id="整库导出与导入"><a href="#整库导出与导入" class="headerlink" title="整库导出与导入"></a>整库导出与导入</h4><ul><li><p>整库导出命令</p><p>  <code>exp system/itcast full=y 或者 exp system/itcast file=文件名 full=y</code></p></li><li><p>整库导入命令</p><p>  <code>imp system/itcast full=y or imp system/itcast full=y file=water.dm</code></p></li></ul><h4 id="按用户导出与导入"><a href="#按用户导出与导入" class="headerlink" title="按用户导出与导入"></a>按用户导出与导入</h4><ul><li><p>按用户导出</p><p>  <code>exp system/itcast owner=wateruser file=wateruser.dmp</code></p></li><li><p>按用户导入</p><p>  <code>imp system/itcast file=wateruser.dmp fromuser=wateruser</code></p></li></ul><h4 id="按表导出与导入"><a href="#按表导出与导入" class="headerlink" title="按表导出与导入"></a>按表导出与导入</h4><ul><li><p>按表导出 </p><p>  <code>exp wateruser/itcast file=a.dmp tables=t_account,a_area</code></p></li><li><p>按表导入 </p><p>  <code>imp wateruser/itcast file=a.dmp tables=t_account,a_are</code></p></li></ul><h3 id="ORACLE-查询"><a href="#ORACLE-查询" class="headerlink" title="ORACLE 查询"></a>ORACLE 查询</h3><h4 id="单表查询"><a href="#单表查询" class="headerlink" title="单表查询"></a>单表查询</h4><h5 id="简单条件查询"><a href="#简单条件查询" class="headerlink" title="简单条件查询"></a>简单条件查询</h5><ul><li>精确查询 select * from T_OWNERS where watermeter=‘30408’</li><li>模糊查询 select * from t_owners where name like ‘%刘%’</li><li>and 运算符 select * from t_owners where name like ‘%刘%’ and housenumber like ‘%5%’</li><li>or 运算符 select * from t_owners where name like ‘%刘%’ or housenumber like ‘%5%’</li><li>and 与 or 运算符混合使用  select * from t_owners where (name like ‘%刘%’ or housenumber like ‘%5%’) and addressid=3</li><li>范围查询 select * from T_ACCOUNT where usenum&gt;=10000 and usenum&lt;=20000</li><li>空值查询 select * from T_PRICETABLE t where maxnum is null</li></ul><h5 id="去掉重复记录"><a href="#去掉重复记录" class="headerlink" title="去掉重复记录"></a>去掉重复记录</h5><p><code>select distinct addressid from T_OWNERS</code></p><h5 id="排序查询"><a href="#排序查询" class="headerlink" title="排序查询"></a>排序查询</h5><ul><li>升序排序 <code>select * from T_ACCOUNT order by usenum</code></li><li>降序排序 <code>select * from T_ACCOUNT order by usenum desc</code></li></ul><h5 id="基于伪列的查询"><a href="#基于伪列的查询" class="headerlink" title="基于伪列的查询"></a>基于伪列的查询</h5><ul><li>ROWID 具体某一行数据的物理地址 select rowID,t.* from T_AREA t</li><li>ROWNUM 每一行的行号,查询后才会标注 select rownum,t.* from T_OWNERTYPE t</li></ul><h5 id="聚合统计"><a href="#聚合统计" class="headerlink" title="聚合统计"></a>聚合统计</h5><ul><li>聚合函数<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">sum* select sum(usenum) from t_account where year&#x3D;‘2012’</span><br><span class="line"></span><br><span class="line">avg* select avg(usenum) from T_ACCOUNT where year&#x3D;‘2012’</span><br><span class="line"></span><br><span class="line">max* select max(usenum) from T_ACCOUNT where year&#x3D;‘2012’</span><br><span class="line"></span><br><span class="line">select* min(usenum) from T_ACCOUNT where year&#x3D;‘2012’</span><br><span class="line"></span><br><span class="line">count* select count(*) from T_OWNERS t where ownertypeid&#x3D;1</span><br></pre></td></tr></table></figure></li><li>分组聚合 <code>Group by* select areaid,sum(money) from t_account group by areaid</code></li><li>分组后条件查询 <code>having* select areaid,sum(money) from t_account group by areaid having sum(money)&gt;169000</code></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> summer </tag>
            
            <tag> database </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> oracle </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MySql数据库知识学习笔记------索引，优化，事务</title>
      <link href="database/mysql/mysql-knowledge/"/>
      <url>database/mysql/mysql-knowledge/</url>
      
        <content type="html"><![CDATA[<div id="article_content" class="article_content clearfix">                                                <div class="article-copyright">                <span class="creativecommons">                <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">                    </a>            <span>                版权声明：本文为博主原创文章，遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议，转载请附上原文出处链接和本声明。            </span>               <div class="article-source-link2222">                    本文链接：<a href="https://blog.csdn.net/bupttulongming/article/details/101466955">https://blog.csdn.net/bupttulongming/article/details/101466955</a>                </div>            </span>                    </div>                                                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">                                        <div id="content_views" class="markdown_views prism-atom-one-dark">                    <!-- flowchart 箭头图标 勿删 -->                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                    </svg>                                            <p><strong>一.事务是什么，事务的四大特性？</strong></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/2019092619334088.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2J1cHR0dWxvbmdtaW5n,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><p><strong>二.并发事务带来的问题</strong></p><ul><li><strong>脏读（Dirty read）</strong>: 当一个事务正在访问数据并且对数据进行了修改，而这种修改还没有提交到数据库中，这时另外一个事务也访问了这个数据，然后使用了这个数据。因为这个数据是还没有提交的数据，那么另外一个事务读到的这个数据是“脏数据”，依据“脏数据”所做的操作可能是不正确的。</li><li><strong>不可重复读（Unrepeatableread）</strong>: 指在一个事务内多次读同一数据。在这个事务还没有结束时，另一个事务也访问该数据。那么，在第一个事务中的两次读数据之间，由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况，因此称为不可重复读。</li><li><strong>幻读（Phantom read）</strong>: 幻读与不可重复读类似。它发生在一个事务（T1）读取了几行数据，接着另一个并发事务（T2）插入了一些数据时。在随后的查询中，第一个事务（T1）就会发现多了一些原本不存在的记录，就好像发生了幻觉一样，所以称为幻读。<br><em><strong>不可重复读和幻读的区别是，一个是多次读同一条数据，发现数据的值不一样了；一个是读取数据时，数据本身并未变化，而是记录的数目变多了。</strong></em></li></ul><p><strong>三.事务的四个隔离级别</strong></p><ol><li><strong>READ-UNCOMMITTED(读取未提交)</strong>： 最低的隔离级别，允许读取尚未提交的数据变更，可能会导致脏读、幻读或不可重复读。</li><li><strong>READ-COMMITTED(读取已提交)</strong>： 允许读取并发事务已经提交的数据，可以阻止脏读，但是幻读或不可重复读仍有可能发生。</li><li><strong>REPEATABLE-READ(可重复读)</strong>： 对同一字段的多次读取结果都是一致的，除非数据是被本身事务自己所修改，可以阻止脏读和不可重复读，但幻读仍有可能发生。</li><li><strong>SERIALIZABLE(可串行化)</strong>： 最高的隔离级别，完全服从ACID的隔离级别。所有的事务依次逐个执行，这样事务之间就完全不可能产生干扰，也就是说，该级别可以防止脏读、不可重复读以及幻读</li></ol><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190926193705742.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2J1cHR0dWxvbmdtaW5n,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br>MYSQL的默认隔离级别是可重复读</p><p><strong>四.MySql数据库底层是B+树</strong></p><p><strong>五.乐观锁&amp;悲观锁</strong></p><ul><li><strong>悲观锁</strong>：总是假设最坏的情况，每次去拿数据的时候都认为别人会修改，所以每次在拿数据的时候都会上锁，这样别人想拿这个数据就会阻塞直到它拿到锁（共享资源每次只给一个线程使用，其它线程阻塞，用完后再把资源转让给其它线程）。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。</li><li><strong>乐观锁</strong>：总是假设最好的情况，每次去拿数据的时候都认为别人不会修改，所以不会上锁，但是在更新的时候会判断一下在此期间别人有没有去更新这个数据，可以使用版本号机制和CAS算法实现。<strong>乐观锁适用于多读的应用类型</strong>，这样可以提高吞吐量，像数据库提供的类似于write_condition机制，其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。</li></ul><p><strong>像乐观锁适用于写比较少的情况下（多读场景），即冲突真的很少发生的时候，这样可以省去了锁的开销，加大了系统的整个吞吐量。但如果是多写的情况，一般会经常产生冲突，这就会导致上层应用会不断的进行retry，这样反倒是降低了性能，所以一般多写的场景下用悲观锁就比较合适。</strong><br><br></p><p><strong>六.乐观锁的实现方式</strong></p><ul><li><p><strong>版本号机制</strong>：一般是在数据表中加上一个数据版本号version字段，表示数据被修改的次数，当数据被修改时，version值会加一。当线程A要更新数据值时，在读取数据的同时也会读取version值，在提交更新时，若刚才读取到的version值为当前数据库中的version值相等时才更新，否则重试更新操作，直到更新成功。</p></li><li><p><strong>CAS</strong>：compare and swap（比较与交换），是一种无锁算法。无锁编程，即不使用锁的情况下实现多线程之间的变量同步，也就是在没有线程被阻塞的情况下实现变量的同步，所以也叫非阻塞同步（Non-blocking Synchronization）。CAS算法涉及到三个操作数：</p><ul><li>需要读写的内存 V</li><li>进行比较的值A</li><li>新值B<br><strong>当且仅当 V 的值等于 A时，CAS通过原子方式用新值B来更新V的值，否则不会执行任何操作（比较和替换是一个原子操作）。一般情况下是一个自旋操作，即不断的重试。</strong></li></ul></li></ul><p><strong>七.自旋锁</strong><br>是指当一个线程在获取锁的时候，如果锁已经被其它线程获取，那么该线程将循环等待，然后不断的判断锁是否能够被成功获取，直到获取到锁才会退出循环。</p><p><strong>八.MyISAM和InnoDB存储引擎使用的锁：</strong></p><ul><li>MyISAM 采用表级锁(table-level locking)</li><li>InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁</li></ul><p><strong>表级锁：Mysql中锁定粒度最大 的一种锁，对当前操作的整张表加锁，实现简单，资源消耗也比较少，加锁快，不会出现死锁。其锁定粒度最大，触发锁冲突的概率最高，并发度最低，MyISAM和 InnoDB引擎都支持表级锁。</strong><br><strong>行级锁： Mysql中锁定 粒度最小 的一种锁，只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小，并发度高，但加锁的开销也最大，加锁慢，会出现死锁。</strong></p><p><strong>九.大表优化</strong></p><p>常见的优化措施：</p><ol><li><strong>限定数据的范围</strong>：务必禁止不带任何限制数据范围条件的查询语句。比如：我们当用户在查询订单历史的时候，我们可以控制在一个月的范围内；</li><li><strong>读/写分离</strong>：经典的数据库拆分方案，主库负责写，从库负责读；</li><li><strong>垂直分区</strong>：根据数据库里面数据表的相关性进行拆分。 例如，用户表中既有用户的登录信息又有用户的基本信息，可以将用户表拆分成两个单独的表，甚至放到单独的库做分库。</li><li><strong>垂直拆分的优点缺点</strong>：优点：可以使得列数据变小，在查询时减少读取的Block数，减少I/O次数。此外，垂直分区可以简化表的结构，易于维护。<strong>缺点：主键会出现冗余</strong>，需要管理冗余列，并会引起Join操作，可以通过在应用层进行Join来解决。此外，垂直分区会让事务变得更加复杂；</li><li><strong>水平分区</strong>：保持数据表结构不变，通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中，达到了分布式的目的。 水平拆分可以支撑非常大的数据量。**水平拆分可以支持非常大的数据量。需要注意的一点是：分表仅仅是解决了单一表数据过大的问题，但由于表的数据还是在同一台机器上，其实对于提升MySQL并发能力没有什么意义，所以 水平拆分最好分库 **</li><li>水平拆分能够 支持非常大的数据量存储，应用端改造也少，但 分片事务难以解决 ，跨节点Join性能较差，逻辑复杂。《Java工程师修炼之道》的作者推荐 尽量不要对数据进行分片，因为拆分会带来逻辑、部署、运维的各种复杂度 ，一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题的。如果实在要分片，尽量选择客户端分片架构，这样可以减少一次和中间件的网络I/O。</li></ol><p><strong>十.SQL查询优化</strong></p><ul><li>可通过开启慢查询日志查找出较慢的SQL.</li><li>不做列运算: SELECT id WHERE age+1=10 ,任何对列的操作都将导致全表扫描.它包括数据库教程函数,计算表达式等等,查询时尽量将操作移至等号右边. —&gt;age=10-1</li><li>SQL语句尽可能简单:一条SQL只能在一个cpu进行运算;大语句拆分成小语句,减少锁时间;一条大SQL可以堵死整个库.</li><li>不用 SELECT *.</li><li>少用 JOIN.</li><li>避免 %xxx式查询.</li><li>不用函数和触发器,在应用程序实现.</li><li>尽量避免在WHERE 子句中使用!= &lt;&gt;操作,否则将导致引擎放弃索引使用全表扫描.</li></ul><pre><code>                                &lt;/div&gt;            &lt;link href=&quot;https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-095d4a0b23.css&quot; rel=&quot;stylesheet&quot;&gt;                &lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于redis，学会这8点就够了</title>
      <link href="database/redis/redis-knowledge/"/>
      <url>database/redis/redis-knowledge/</url>
      
        <content type="html"><![CDATA[<div class="htmledit_views" id="content_views">                                            <p style="margin-left:10px;"><strong>1，redis是什么</strong></p><p style="margin-left:10px;"><a href="https://www.huaweicloud.com/product/dcs.html?wx" rel="nofollow" data-token="f27424da9cfb05f20ea8d00dc1ead38b">redis</a>是一种支持Key-Value等多种数据结构的存储系统。可用于缓存，事件发布或订阅，高速队列等场景。该数据库使用ANSI C语言编写，支持网络，提供字符串，哈希，列表，队列，集合结构直接存取，基于内存，可持久化。</p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;"><strong>2，支持的语言</strong></p><p style="margin-left:10px;"><img alt="" class="has" height="105" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405267" width="553"></p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;"><strong>3，redis的应用场景有哪些</strong></p><p style="margin-left:10px;">1，会话缓存（最常用）<br>2，消息队列，<br>比如支付3，活动排行榜或计数<br>4，发布，订阅消息（消息通知）<br>5，商品列表，评论列表等</p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;"><strong>4，redis数据类型</strong><br><strong><u><a href="https://www.huaweicloud.com/product/dcs.html?wx" rel="nofollow" data-token="f27424da9cfb05f20ea8d00dc1ead38b"><span style="color:#f33b45;">Redis</span></a></u></strong>一共支持五种数据类：string（字符串），hash（哈希），list（列表），set（集合）和zset（sorted set有序集合）。</p><p style="margin-left:10px;">（1）字符串（字符串）<br>它是redis的最基本的数据类型，一个键对应一个值，需要注意是一个键值最大存储512MB。</p><p style="margin-left:10px;"><img alt="" class="has" height="225" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405288" width="554"></p><p style="margin-left:10px;">（2）hash（哈希）<br>redis hash是一个键值对的集合，是一个string类型的field和value的映射表，适合用于存储对象</p><p style="margin-left:10px;"><img alt="" class="has" height="244" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405306" width="644"></p><p style="margin-left:10px;">（3）表（列表）<br>是redis的简单的字符串列表，它按插入顺序排序</p><p style="margin-left:10px;"><img alt="" class="has" height="227" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405324" width="637"></p><p style="margin-left:10px;">（4）组（集合）<br>是字符串类型的无序集合，也不可重复</p><p style="margin-left:10px;"><img alt="" class="has" height="499" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405342" width="634"></p><p style="margin-left:10px;">（5）zset（sorted set有序集合）<br>是string类型的有序集合，也不可重复<br>有序集合中的每个元素都需要指定一个分数，根据分数对元素进行升序排序，如果多个元素有相同的分数，则以字典序进行升序排序，sorted set因此非常适合实现排名</p><p style="margin-left:10px;"><img alt="" class="has" height="671" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405363" width="626"></p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;"><strong>5，redis的服务相关的命令</strong></p><p style="margin-left:10px;"><img alt="" class="has" height="478" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405380" width="628"></p><p style="margin-left:10px;">slect＃选择数据库（数据库编号0-15）<br>退出＃退出连接<br>信息＃获得服务的信息与统计<br>monitor＃实时监控<br>config get＃获得服务配置<br>flushdb＃删除当前选择的数据库中的key<br>flushall＃删除所有数据库中的键</p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;"><strong>6，redis的发布与订阅</strong></p><p style="margin-left:10px;">redis的发布与订阅（发布/订阅）是它的一种消息通信模式，一方发送信息，一方接收信息。<br>下图是三个客户端同时订阅同一个频道</p><p style="margin-left:10px;"><img alt="" class="has" height="198" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405400" width="319"></p><p style="margin-left:10px;">下图是有新信息发送给频道1时，就会将消息发送给订阅它的三个客户端<br><img alt="" class="has" height="285" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405417" width="315"></p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;"><strong>7，redis的持久化</strong></p><p style="margin-left:10px;">redis持久有两种方式：快照（快照），仅附加文件（AOF）</p><p style="margin-left:10px;">快照（快照）</p><p style="margin-left:10px;">1，将存储在内存的数据以快照的方式写入二进制文件中，如默认dump.rdb中<br>2，保存900 1&nbsp;</p><p style="margin-left:10px;">＃900秒内如果超过1个Key被修改，则启动快照保存<br>3，保存300 10&nbsp;</p><p style="margin-left:10px;">＃300秒内如果超过10个Key被修改，则启动快照保存<br>4，保存60 10000&nbsp;</p><p style="margin-left:10px;">＃60秒内如果超过10000个重点被修改，则启动快照保存<br>&nbsp;</p><p style="margin-left:10px;">仅附加文件（AOF）</p><p style="margin-left:10px;">1，使用AOF持久时，服务会将每个收到的写命令通过写函数追加到文件中（appendonly.aof）<br>2，AOF持久化存储方式参数说明<br>&nbsp; &nbsp;&nbsp;appendonly yes &nbsp;</p><p style="margin-left:10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;＃开启AOF持久化存储方式&nbsp;<br>&nbsp; &nbsp; appendfsync always&nbsp;</p><p style="margin-left:10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;＃收到写命令后就立即写入磁盘，效率最差，效果最好<br>&nbsp; &nbsp; appendfsync everysec</p><p style="margin-left:10px;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;＃每秒写入磁盘一次，效率与效果居中<br>&nbsp; &nbsp; appendfsync no&nbsp;</p><p style="margin-left:10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;＃完全依赖操作系统，效率最佳，效果没法保证</p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;"><strong>8，redis的性能测试</strong></p><p style="margin-left:10px;">自带相关测试工具</p><p style="margin-left:10px;"><img alt="" class="has" height="779" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405438" width="570"></p><p style="margin-left:10px;">实际测试同时执行100万的请求</p><p style="margin-left:10px;"><img alt="" class="has" height="299" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181224163405456" width="632"></p><p style="margin-left:10px;">&nbsp;</p><p style="margin-left:10px;">【本文由<strong><a href="https://www.huaweicloud.com/product/dcs.html?wx" rel="nofollow" data-token="f27424da9cfb05f20ea8d00dc1ead38b">中间件小哥</a></strong>收集整理自“民工哥的Linux的运维”】</p>                                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Nosql简介 Redis，Memchche,MongoDb的区别</title>
      <link href="database/nosql-introduce/"/>
      <url>database/nosql-introduce/</url>
      
        <content type="html"><![CDATA[<style>      h4{        line-height: 30px;        font-size: 20px;        }</style><div id="cnblogs_post_body" class="blogpost-body cnblogs-markdown">    <h2 id="本篇文章主要介绍nosql的一些东西以及nosql中比较火的三个数据库redismemchachemongodb和他们之间的区别以下是本文章的阅读目录">本篇文章主要介绍Nosql的一些东西，以及Nosql中比较火的三个数据库Redis、Memchache、MongoDb和他们之间的区别。以下是本文章的阅读目录</h2><!-- <h3 id="一nosql介绍">一、Nosql介绍</h3> --><p>1.<a href="#item1">Nosql简介</a><br>2.<a href="#item2">Nosql的特点和关系型数据库的区别</a><br>3.<a href="#item3">Redis，Memcache，MongoDb的特点与区别</a><br>4<a href="#item4">.参考文章</a><br><br></p><h1 id="nosql介绍"><span id="item1">Nosql介绍</span></h1><h4 id="nosql的全称是not-only-sql这个概念早起就有人提出在09年的时候比较火nosql指的是非关系型数据库而我们常用的都是关系型数据库就像我们常用的mysqlsqlserver一样这些数据库一般用来存储重要信息应对普通的业务是没有问题的但是随着互联网的高速发展传统的关系型数据库在应付超大规模超大流量以及高并发的时候力不从心而就在这个时候nosql得到的告诉的发展">Nosql的全称是Not Only Sql，这个概念早起就有人提出，在09年的时候比较火。Nosql指的是非关系型数据库，而我们常用的都是关系型数据库。就像我们常用的mysql，sqlserver一样，这些数据库一般用来存储重要信息，应对普通的业务是没有问题的。但是，随着互联网的高速发展，传统的关系型数据库在应付超大规模，超大流量以及高并发的时候力不从心。而就在这个时候，Nosql得到的告诉的发展。</h4><p><br></p><h1 id="nosql和关系型数据库的区别"><span id="item2">Nosql和关系型数据库的区别</span></h1><h3 id="存储方式">1.存储方式</h3><h4 id="关系型数据库是表格式的因此存储在表的行和列中他们之间很容易关联协作存储提取数据很方便而nosql数据库则与其相反他是大块的组合在一起通常存储在数据集中就像文档键值对或者图结构">　　关系型数据库是表格式的，因此存储在表的行和列中。他们之间很容易关联协作存储，提取数据很方便。而Nosql数据库则与其相反，他是大块的组合在一起。通常存储在数据集中，就像文档、键值对或者图结构。</h4><p><br></p><h3 id="存储结构">2.存储结构</h3><h4 id="关系型数据库对应的是结构化数据数据表都预先定义了结构列的定义结构描述了数据的形式和内容这一点对数据建模至关重要虽然预定义结构带来了可靠性和稳定性但是修改这些数据比较困难而nosql数据库基于动态结构使用与非结构化数据因为nosql数据库是动态结构可以很容易适应数据类型和结构的变化">　　关系型数据库对应的是结构化数据，数据表都预先定义了结构（列的定义），结构描述了数据的形式和内容。这一点对数据建模至关重要，虽然预定义结构带来了可靠性和稳定性，但是修改这些数据比较困难。而Nosql数据库基于动态结构，使用与非结构化数据。因为Nosql数据库是动态结构，可以很容易适应数据类型和结构的变化。</h4><p><br></p><h3 id="存储规范">3.存储规范</h3><h4 id="关系型数据库的数据存储为了更高的规范性把数据分割为最小的关系表以避免重复获得精简的空间利用虽然管理起来很清晰但是单个操作设计到多张表的时候数据管理就显得有点麻烦而nosql数据存储在平面数据集中数据经常可能会重复单个数据库很少被分隔开而是存储成了一个整体这样整块数据更加便于读写">　　关系型数据库的数据存储为了更高的规范性，把数据分割为最小的关系表以避免重复，获得精简的空间利用。虽然管理起来很清晰，但是单个操作设计到多张表的时候，数据管理就显得有点麻烦。而Nosql数据存储在平面数据集中，数据经常可能会重复。单个数据库很少被分隔开，而是存储成了一个整体，这样整块数据更加便于读写</h4><p><br></p><h3 id="存储扩展">4.存储扩展</h3><h4 id="这可能是两者之间最大的区别关系型数据库是纵向扩展也就是说想要提高处理能力要使用速度更快的计算机因为数据存储在关系表中操作的性能瓶颈可能涉及到多个表需要通过提升计算机性能来克服虽然有很大的扩展空间但是最终会达到纵向扩展的上限而nosql数据库是横向扩展的它的存储天然就是分布式的可以通过给资源池添加更多的普通数据库服务器来分担负载">　　这可能是两者之间最大的区别，关系型数据库是纵向扩展，也就是说想要提高处理能力，要使用速度更快的计算机。因为数据存储在关系表中，操作的性能瓶颈可能涉及到多个表，需要通过提升计算机性能来克服。虽然有很大的扩展空间，但是最终会达到纵向扩展的上限。而Nosql数据库是横向扩展的，它的存储天然就是分布式的，可以通过给资源池添加更多的普通数据库服务器来分担负载。</h4><p><br></p><h3 id="查询方式">5.查询方式</h3><h4 id="关系型数据库通过结构化查询语言来操作数据库就是我们通常说的sqlsql支持数据库curd操作的功能非常强大是业界的标准用法而nosql查询以块为单元操作数据使用的是非结构化查询语言unql它是没有标准的关系型数据库表中主键的概念对应nosql中存储文档的id关系型数据库使用预定义优化方式比如索引来加快查询操作而nosql更简单更精确的数据访问模式">　　关系型数据库通过结构化查询语言来操作数据库（就是我们通常说的SQL）。SQL支持数据库CURD操作的功能非常强大，是业界的标准用法。而Nosql查询以块为单元操作数据，使用的是非结构化查询语言（UnQl），它是没有标准的。关系型数据库表中主键的概念对应Nosql中存储文档的ID。关系型数据库使用预定义优化方式（比如索引）来加快查询操作，而Nosql更简单更精确的数据访问模式。</h4><p><br></p><h3 id="事务">6.事务</h3><h4 id="关系型数据库遵循acid规则原子性atomicity一致性consistency隔离性isolation持久性durability而nosql数据库遵循base原则基本可用basically-availble软柔性事务soft-state-最终一致性eventual-consistency由于关系型数据库的数据强一致性所以对事务的支持很好关系型数据库支持对事务原子性细粒度控制并且易于回滚事务而nosql数据库是在cap一致性可用性分区容忍度中任选两项因为基于节点的分布式系统中很难全部满足所以对事务的支持不是很好虽然也可以使用事务但是并不是nosql的闪光点">　　关系型数据库遵循ACID规则（原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)），而Nosql数据库遵循BASE原则（基本可用（Basically Availble）、软/柔性事务（Soft-state ）、最终一致性（Eventual Consistency））。由于关系型数据库的数据强一致性，所以对事务的支持很好。关系型数据库支持对事务原子性细粒度控制，并且易于回滚事务。而Nosql数据库是在CAP（一致性、可用性、分区容忍度）中任选两项，因为基于节点的分布式系统中，很难全部满足，所以对事务的支持不是很好，虽然也可以使用事务，但是并不是Nosql的闪光点。</h4><p><br></p><h3 id="性能">7.性能</h3><h4 id="关系型数据库为了维护数据的一致性付出了巨大的代价读写性能比较差在面对高并发读写性能非常差面对海量数据的时候效率非常低而nosql存储的格式都是key-value类型的并且存储在内存中非常容易存储而且对于数据的-一致性是-弱要求nosql无需sql的解析提高了读写性能">　　关系型数据库为了维护数据的一致性付出了巨大的代价，读写性能比较差。在面对高并发读写性能非常差，面对海量数据的时候效率非常低。而Nosql存储的格式都是key-value类型的，并且存储在内存中，非常容易存储，而且对于数据的 一致性是 弱要求。Nosql无需sql的解析，提高了读写性能。</h4><p><br></p><h3 id="授权方式">8.授权方式</h3><h4 id="关系型数据库通常有sql-servermysqloracle主流的nosql数据库有redismemcachemongodb大多数的关系型数据库都是付费的并且价格昂贵成本较大而nosql数据库通常都是开源的">　　关系型数据库通常有SQL Server，Mysql，Oracle。主流的Nosql数据库有redis，memcache，MongoDb。大多数的关系型数据库都是付费的并且价格昂贵，成本较大，而Nosql数据库通常都是开源的。</h4><p><br></p><h1 id="redismemcachemongodb的特点与区别"><span id="item3">Redis，Memcache，MongoDb的特点与区别</span></h1><p><br></p><h2 id="redis">Redis</h2><h3 id="优点">优点</h3><h4 id="支持多种数据结构如-string字符串-list双向链表dicthash表set集合zset排序sethyperloglog基数估算-2.支持持久化操作可以进行aof及rdb数据持久化到磁盘从而进行数据备份或数据恢复等操作较好的防止数据丢失的手段-3.支持通过replication进行数据复制通过master-slave机制可以实时进行数据的同步复制支持多级复制和增量复制master-slave机制是redis进行ha的重要手段-4.单线程请求所有命令串行执行并发情况下不需要考虑数据一致性问题-5.支持pubsub消息订阅机制可以用来进行消息订阅与通知-6.支持简单的事务需求但业界使用场景很少并不成熟">1.支持多种数据结构，如 string（字符串）、 list(双向链表)、dict(hash表)、set(集合）、zset(排序set)、hyperloglog（基数估算）<br>2.支持持久化操作，可以进行aof及rdb数据持久化到磁盘，从而进行数据备份或数据恢复等操作，较好的防止数据丢失　　的手段。<br>3.支持通过Replication进行数据复制，通过master-slave机制，可以实时进行数据的同步复制，支持多级复制和增量复制，master-slave机制是Redis进行HA的重要手段。<br>4.单线程请求，所有命令串行执行，并发情况下不需要考虑数据一致性问题。<br>5.支持pub/sub消息订阅机制，可以用来进行消息订阅与通知。<br>6.支持简单的事务需求，但业界使用场景很少，并不成熟。</h4><h3 id="缺点">缺点</h3><h4 id="redis只能使用单线程性能受限于cpu性能故单实例cpu最高才可能达到5-6wqps每秒取决于数据结构数据大小以及服务器硬件性能日常环境中qps高峰大约在1-2w左右-2.支持简单的事务需求但业界使用场景很少并不成熟既是优点也是缺点-3.redis在string类型上会消耗较多内存可以使用dicthash表压缩存储以降低内存耗用">1.Redis只能使用单线程，性能受限于CPU性能，故单实例CPU最高才可能达到5-6wQPS每秒（取决于数据结构，数据大小以及服务器硬件性能，日常环境中QPS高峰大约在1-2w左右）。<br>2.支持简单的事务需求，但业界使用场景很少，并不成熟，既是优点也是缺点。<br>3.Redis在string类型上会消耗较多内存，可以使用dict（hash表）压缩存储以降低内存耗用。</h4><p><br></p><h2 id="memcache">Memcache</h2><h3 id="优点-1">优点</h3><h4 id="memcached可以利用多核优势单实例吞吐量极高可以达到几十万qps取决于keyvalue的字节大小以及服务器硬件性能日常环境中qps高峰大约在4-6w左右适用于最大程度扛量-2.支持直接配置为session-handle">1.Memcached可以利用多核优势，单实例吞吐量极高，可以达到几十万QPS（取决于key、value的字节大小以及服务器硬件性能，日常环境中QPS高峰大约在4-6w左右）。适用于最大程度扛量。<br>2.支持直接配置为session handle。</h4><h3 id="缺点-1">缺点</h3><h4 id="只支持简单的keyvalue数据结构不像redis可以支持丰富的数据类型-2.无法进行持久化数据不能备份只能用于缓存使用且重启后数据全部丢失-3.无法进行数据同步不能将mc中的数据迁移到其他mc实例中-4.memcached内存分配采用slab-allocation机制管理内存value大小分布差异较大时会造成内存利用率降低并引发低利用率时依然出现踢出等问题需要用户注重value设计">1只支持简单的key/value数据结构，不像Redis可以支持丰富的数据类型。<br>2.无法进行持久化，数据不能备份，只能用于缓存使用，且重启后数据全部丢失。<br>3.无法进行数据同步，不能将MC中的数据迁移到其他MC实例中。<br>4.Memcached内存分配采用Slab Allocation机制管理内存，value大小分布差异较大时会造成内存利用率降低，并引发低利用率时依然出现踢出等问题。需要用户注重value设计。</h4><p><br></p><h2 id="mongodb">MongoDB</h2><h3 id="优点-2">优点</h3><h4 id="更高的写负载mongodb拥有更高的插入速度-2.处理很大的规模的单表当数据表太大的时候可以很容易的分割表-3.高可用性设置m-s不仅方便而且很快mongodb还可以快速安全及自动化的实现节点数据中心故障转移-4.快速的查询mongodb支持二维空间索引比如管道因此可以快速及精确的从指定位置获取数据mongodb在启动后会将数据库中的数据以文件映射的方式加载到内存中如果内存资源相当丰富的话这将极大地提高数据库的查询速度-5.非结构化数据的爆发增长增加列在有些情况下可能锁定整个数据库或者增加负载从而导致性能下降由于mongodb的弱数据结构模式添加1个新字段不会对旧表格有任何影响整个过程会非常快速">1.更高的写负载，MongoDB拥有更高的插入速度。<br>2.处理很大的规模的单表，当数据表太大的时候可以很容易的分割表。<br>3.高可用性，设置M-S不仅方便而且很快，MongoDB还可以快速、安全及自动化的实现节点（数据中心）故障转移。<br>4.快速的查询，MongoDB支持二维空间索引，比如管道，因此可以快速及精确的从指定位置获取数据。MongoDB在启动后会将数据库中的数据以文件映射的方式加载到内存中。如果内存资源相当丰富的话，这将极大地提高数据库的查询速度。<br>5.非结构化数据的爆发增长，增加列在有些情况下可能锁定整个数据库，或者增加负载从而导致性能下降，由于MongoDB的弱数据结构模式，添加1个新字段不会对旧表格有任何影响，整个过程会非常快速。</h4><h3 id="缺点-2">缺点</h3><h4 id="不支持事务-2.mongodb占用空间过大-3.mongodb没有成熟的维护工具">1.不支持事务。<br>2.MongoDB占用空间过大 。<br>3.MongoDB没有成熟的维护工具。</h4><p><br></p><h2 id="redismemcache和mongodb的区别">Redis、Memcache和MongoDB的区别</h2><h3 id="性能-1">1.性能</h3><h4 id="三者的性能都比较高总的来讲memcache和redis差不多要高于mongodb">三者的性能都比较高，总的来讲：Memcache和Redis差不多，要高于MongoDB。</h4><h3 id="便利性">2.便利性</h3><h4 id="memcache数据结构单一-redis丰富一些数据操作方面redis更好一些较少的网络io次数-mongodb支持丰富的数据表达索引最类似关系型数据库支持的查询语言非常丰富">memcache数据结构单一。<br>redis丰富一些，数据操作方面，redis更好一些，较少的网络IO次数。<br>mongodb支持丰富的数据表达，索引，最类似关系型数据库，支持的查询语言非常丰富。</h4><h3 id="存储空间">3,存储空间</h3><h4 id="redis在2.0版本后增加了自己的vm特性突破物理内存的限制可以对key-value设置过期时间类似memcache-memcache可以修改最大可用内存采用lru算法-mongodb适合大数据量的存储依赖操作系统vm做内存管理吃内存也比较厉害服务不要和别的服务在一起">redis在2.0版本后增加了自己的VM特性，突破物理内存的限制；可以对key value设置过期时间（类似memcache）。<br>memcache可以修改最大可用内存,采用LRU算法。<br>mongoDB适合大数据量的存储，依赖操作系统VM做内存管理，吃内存也比较厉害，服务不要和别的服务在一起。</h4><h3 id="可用性">4.可用性</h3><h4 id="redis依赖客户端来实现分布式读写主从复制时每次从节点重新连接主节点都要依赖整个快照无增量复制因性能和效率问题所以单点问题比较复杂不支持自动sharding需要依赖程序设定一致hash-机制一种替代方案是不用redis本身的复制机制采用自己做主动复制多份存储或者改成增量复制的方式需要自己实现一致性问题和性能的权衡-memcache本身没有数据冗余机制也没必要对于故障预防采用依赖成熟的hash或者环状的算法解决单点故障引起的抖动问题-mongodb支持master-slavereplicaset内部采用paxos选举算法自动故障恢复auto-sharding机制对客户端屏蔽了故障转移和切分机制">redis，依赖客户端来实现分布式读写；主从复制时，每次从节点重新连接主节点都要依赖整个快照,无增量复制，因性能和效率问题，所以单点问题比较复杂；不支持自动sharding,需要依赖程序设定一致hash 机制。一种替代方案是，不用redis本身的复制机制，采用自己做主动复制（多份存储），或者改成增量复制的方式（需要自己实现），一致性问题和性能的权衡。<br>Memcache本身没有数据冗余机制，也没必要；对于故障预防，采用依赖成熟的hash或者环状的算法，解决单点故障引起的抖动问题。<br>mongoDB支持master-slave,replicaset（内部采用paxos选举算法，自动故障恢复）,auto sharding机制，对客户端屏蔽了故障转移和切分机制。</h4><h3 id="可靠性">5.可靠性</h3><h4 id="redis支持快照aof依赖快照进行持久化aof增强了可靠性的同时对性能有所影响-memcache不支持通常用在做缓存提升性能-mongodb从1.8版本开始采用binlog方式支持持久化的可靠性">redis支持（快照、AOF）：依赖快照进行持久化，aof增强了可靠性的同时，对性能有所影响。<br>memcache不支持，通常用在做缓存,提升性能。<br>MongoDB从1.8版本开始采用binlog方式支持持久化的可靠性。</h4><h3 id="一致性">6.一致性</h3><h4 id="memcache-在并发场景下用cas保证一致性-redis事务支持比较弱只能保证事务中的每个操作连续执行-mongodb不支持事务">Memcache 在并发场景下，用cas保证一致性。<br>redis事务支持比较弱，只能保证事务中的每个操作连续执行。<br>mongoDB不支持事务。</h4><h3 id="数据分析">7.数据分析</h3><h4 id="mongodb内置了数据分析的功能mapreduce其他两者不支持">mongoDB内置了数据分析的功能(mapreduce),其他两者不支持。</h4><h3 id="应用场景">8.应用场景</h3><h4 id="redis数据量较小的更性能操作和运算上-memcache用于在动态系统中减少数据库负载提升性能做缓存提高性能适合读多写少对于数据量比较大可以采用sharding-mongodb主要解决海量数据的访问效率问题">redis：数据量较小的更性能操作和运算上。<br>memcache：用于在动态系统中减少数据库负载，提升性能;做缓存，提高性能（适合读多写少，对于数据量比较大，可以采用sharding）。<br><a href="MongoDB:主要解决海量数据的访问效率问题。####" class="uri">MongoDB:主要解决海量数据的访问效率问题。####</a></h4><p><br></p><h1 id="参考文章"><span id="item4">参考文章</span></h1><h4 id="redismemcache和mongodb的区别-1"><a href="http://www.cnblogs.com/tuyile006/p/6382062.html">Redis、Memcache和MongoDB的区别</a></h4></div>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Oracle数据库简介</title>
      <link href="database/oracle-introduce/"/>
      <url>database/oracle-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p>Oracle Database，又名Oracle RDBMS，或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统，系统可移植性好、使用方便、功能强，适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的 适应高吞吐量的数据库解决方案。</p><p>ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品，是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。比如SilverStream就是基于数据库的一种中间件。ORACLE数据库是目前世界上使用最为广泛的数据库管理系统，作为一个通用的数据库系统，它具有完整的数据管理功能;作为一个关系数据库，它是一个完备关系的产品;作为分布式数据库它实现了分布式处理功能。但它的所有知识，只要在一种机型上学习了ORACLE知识，便能在各种类型的机器上使用它。</p><p>Oracle数据库最新版本为Oracle Database 12c。Oracle数据库12c 引入了一个新的多承租方架构，使用该架构可轻松部署和管理数据库云。此外，一些创新特性可最大限度地提高资源使用率和灵活性，如Oracle Multitenant可快速整合多个数据库，而Automatic Data Optimization和Heat Map能以更高的密度压缩数据和对数据分层。这些独一无二的技术进步再加上在可用性、安全性和大数据支持方面的主要增强，使得Oracle数据库12c 成为私有云和公有云部署的理想平台。</p><h3 id="Oracle数据库支持平台"><a href="#Oracle数据库支持平台" class="headerlink" title="Oracle数据库支持平台"></a>Oracle数据库支持平台</h3><p>在2001年发布的Oracle9i之前，甲骨文公司把他们的数据库产品广泛的移植到了不同的平台上。近期，甲骨文公司巩固了一小部分的操作系统平台。</p><p>截止至2015年01月，甲骨文公司的Oracle10g/11g/12c支持以下的操作系统和硬件:</p><p>· AppleMac OS X Server:PowerPC</p><p>· HPHP-UX:PA-RISC,Itanium</p><p>· HPTru64 UNIX:Alpha</p><p>· HPOpenVMS: Alpha, Itanium</p><p>· IBMAIX5L:IBM POWER</p><p>· IBMz/OS:zSeries</p><p>· Linux:x86,x86-64, PowerPC, zSeries, Itanium</p><p>· MicrosoftWindows: x86, x86-64, Itanium</p><p>· SunSolaris:SPARC, x86, x86-64</p><h3 id="Oracle数据库管理及开发工具"><a href="#Oracle数据库管理及开发工具" class="headerlink" title="Oracle数据库管理及开发工具"></a>Oracle数据库管理及开发工具</h3><p>·Navicat for Oracle是一套专为Oracle设计的强大数据库管理及开发工具。它可以用于任何版本的Oracle数据库，并支援大部份Oracle的功能，包括触发器、索引、检视等。</p><p>·Toad for Oracle是一款老牌的Oracle开发管理工具，比任何一款Oracle开发管理工具功能更多，并针对使用者不同的角色有多个分支版本。版本包括:Toad DBA Suite for Oracle是一款专门为Oracle DBA管理Oracle数据库工具, Toad Development Suite for Oracle是一款专门为Oracle开发工具， Toad DBA Suite for Oracle – Exadata Edition是一款专门为Oracle Exadata一体服务器及Oracle数据库管理工具, Toad DBA Suite for Oracle - RAC Edition是一款专门为Oracle搭建集群RAC的DBA管理工具</p><h3 id="Oracle数据库结构"><a href="#Oracle数据库结构" class="headerlink" title="Oracle数据库结构"></a>Oracle数据库结构</h3><p>它由至少一个表空间和数据库模式对象组成。这里，模式是对象的集合，而模式对象是直接引用数据库数据的逻辑结构。模式对象包括这样一些结构:表、视图、序列、存储过程、同义词、索引、簇和数据库链等。逻辑存储结构包括表空间、段和范围，用于描述怎样使用数据库的物理空间。</p><p>总之,逻辑结构由逻辑存储结构(表空间,段,范围,块)和逻辑数据结构(表、视图、序列、存储过程、同义词、索引、簇和数据库链等)组成,而其中的模式对象(逻辑数据结构)和关系形成了数据库的关系设计。</p><p>段(Segment):</p><p>是表空间中一个指定类型的逻辑存储结构，它由一个或多个范围组成，段将占用并增长存储空间。</p><p>数据库的物理存储结构是由一些多种物理文件组成，主要有数据文件、控制文件、重做日志文件、归档日志文件、参数文件、口令文件、警告文件等。</p><p>控制文件:存储实例、数据文件及日志文件等信息的二进制文件。alter system set control_files=’路径’。V$CONTROLFILE。</p><p>数据文件:存储数据，以.dbf做后缀。一句话:一个表空间对多个数据文件，一个数据文件只对一个表空间。dba_data_files/v$datafile。</p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> oracle </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>MongoDB数据库简介</title>
      <link href="database/mongodb/mongodb-introduce/"/>
      <url>database/mongodb/mongodb-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="什么是MongoDB"><a href="#什么是MongoDB" class="headerlink" title="什么是MongoDB ?"></a>什么是MongoDB ?</h3><p>MongoDB 是由C++语言编写的开源数据库系统。  </p><p>在高负载的情况下，添加更多的节点，可以保证服务器性能。  </p><p>MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。  </p><p>mongodb-logo<br>MongoDB 将数据存储为一个文档。MongoDB是一个基于分布式文件存储的数据库。  </p><p> FirstName=”Arun”, Address=”St. Xavier’s Road”, Spouse=[{Name:”Kiran”}], Children=[{Name:”Rihit”, Age:8}].<br> FirstName=”Sameer”,Address=”8 Gandhi Road”.   </p><p>注意：以上数据有两个不同的文档（以”.”分隔）。以这种方式存储数据即为文件存储的数据库。 MongoDB是一个面向文档的数据库。  </p><h3 id="主要特点"><a href="#主要特点" class="headerlink" title="主要特点"></a>主要特点</h3><p>MongoDB的提供了一个面向文档存储，操作起来比较简单和容易。<br>你可以在MongoDB记录中设置任何属性的索引 (如：FirstName=”Sameer”,Address=”8 Gandhi Road”)来实现更快的排序。<br>你可以通过本地或者网络创建数据镜像，这使得MongoDB有更强的扩展性。<br>如果负载的增加（需要更多的存储空间和更强的处理能力） ，它可以分布在计算机网络中的其他节点上这就是所谓的分片。<br>Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记，可轻易查询文档中内嵌的对象及数组。<br>MongoDb 使用update()命令可以实现替换完成的文档（数据）或者一些指定的数据字段 。<br>Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。<br>Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录，将key与value传给Reduce函数进行处理。<br>Map函数和Reduce函数是使用Javascript编写的，并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。<br>GridFS是MongoDB中的一个内置功能，可以用于存放大量小文件。<br>MongoDB允许在服务端执行脚本，可以用Javascript编写某个函数，直接在服务端执行，也可以把函数的定义存储在服务端，下次直接调用即可。<br>MongoDB支持各种编程语言:RUBY，PYTHON，JAVA，C++，PHP，C#等多种语言。<br>MongoDB安装简单。  </p><h3 id="历史-2007年10月，MongoDB由10gen团队所发展。2009年2月首度推出。"><a href="#历史-2007年10月，MongoDB由10gen团队所发展。2009年2月首度推出。" class="headerlink" title="历史 2007年10月，MongoDB由10gen团队所发展。2009年2月首度推出。"></a>历史 2007年10月，MongoDB由10gen团队所发展。2009年2月首度推出。</h3><p>2012年05月23日，MongoDB2.1 开发分支发布了! 该版本采用全新架构，包含诸多增强。<br>2012年06月06日，MongoDB 2.0.6 发布，分布式文档数据库。<br>2013年04月23日，MongoDB 2.4.3 发布，此版本包括了一些性能优化，功能增强以及bug修复。<br>2013年08月20日，MongoDB 2.4.6 发布，是目前最新的稳定版。  </p><h3 id="MongoDB-下载"><a href="#MongoDB-下载" class="headerlink" title="MongoDB 下载"></a>MongoDB 下载</h3><p>你可以在mongodb官网下载该安装包，地址为： <a href="http://www.mongodb.org/downloads%E3%80%82MonggoDB%E6%94%AF%E6%8C%81%E4%BB%A5%E4%B8%8B%E5%B9%B3%E5%8F%B0">http://www.mongodb.org/downloads。MonggoDB支持以下平台</a>:  </p><p>OS X 32-bit<br>OS X 64-bit<br>Linux 32-bit<br>Linux 64-bit<br>Windows 32-bit<br>Windows 64-bit<br>Solaris i86pc<br>Solaris 64  </p><h3 id="MongoDB-工具"><a href="#MongoDB-工具" class="headerlink" title="MongoDB 工具"></a>MongoDB 工具</h3><p>有几种可用于MongoDB的管理工具。  </p><p>监控<br>MongoDB提供了网络和系统监控工具Munin，它作为一个插件应用于MongoDB中。  </p><p>Gangila是MongoDB高性能的系统监视的工具，它作为一个插件应用于MongoDB中。  </p><p>基于图形界面的开源工具 Cacti, 用于查看CPU负载, 网络带宽利用率,它也提供了一个应用于监控 MongoDB 的插件。  </p><p>GUI<br>Fang of Mongo – 网页式,由Django和jQuery所构成。<br>Futon4Mongo – 一个CouchDB Futon web的mongodb山寨版。<br>Mongo3 – Ruby写成。<br>MongoHub – 适用于OSX的应用程序。<br>Opricot – 一个基于浏览器的MongoDB控制台, 由PHP撰写而成。<br>Database Master — Windows的mongodb管理工具<br>RockMongo — 最好的PHP语言的MongoDB管理工具，轻量级, 支持多国语言.  </p><h3 id="MongoDB-应用案例"><a href="#MongoDB-应用案例" class="headerlink" title="MongoDB 应用案例"></a>MongoDB 应用案例</h3><p>下面列举一些公司MongoDB的实际应用：  </p><p>Craiglist上使用MongoDB的存档数十亿条记录。<br>FourSquare，基于位置的社交网站，在Amazon EC2的服务器上使用MongoDB分享数据。<br>Shutterfly，以互联网为基础的社会和个人出版服务，使用MongoDB的各种持久性数据存储的要求。<br>bit.ly, 一个基于Web的网址缩短服务，使用MongoDB的存储自己的数据。<br>spike.com，一个MTV网络的联营公司， spike.com使用MongoDB的。<br>Intuit公司，一个为小企业和个人的软件和服务提供商，为小型企业使用MongoDB的跟踪用户的数据。<br>sourceforge.net，资源网站查找，创建和发布开源软件免费，使用MongoDB的后端存储。<br>etsy.com ，一个购买和出售手工制作物品网站，使用MongoDB。<br>纽约时报，领先的在线新闻门户网站之一，使用MongoDB。<br>CERN，著名的粒子物理研究所，欧洲核子研究中心大型强子对撞机的数据使用MongoDB。</p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mongodb </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Mysql数据库简介</title>
      <link href="database/mysql/mysql-introduce/"/>
      <url>database/mysql/mysql-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="什么是数据库？"><a href="#什么是数据库？" class="headerlink" title="什么是数据库？"></a>什么是数据库？</h3><p>数据库（Database）是按照数据结构来组织、存储和管理数据的仓库，  </p><p>每个数据库都有一个或多个不同的API用于创建，访问，管理，搜索和复制所保存的数据。  </p><p>我们也可以将数据存储在文件中，但是在文件中读写数据速度相对较慢。  </p><p>所以，现在我们使用关系型数据库管理系统（RDBMS）来存储和管理的大数据量。所谓的关系型数据库，是建立在关系模型基础上的数据库，借助于集合代数等数学概念和方法来处理数据库中的数据。  </p><p>RDBMS即关系数据库管理系统(Relational Database Management System)的特点：  </p><ol><li>数据以表格的形式出现  </li><li>每行为各种记录名称  </li><li>每列为记录名称所对应的数据域  </li><li>许多的行和列组成一张表单  </li><li>若干的表单组成database      </li></ol><h3 id="RDBMS-术语"><a href="#RDBMS-术语" class="headerlink" title="RDBMS 术语"></a>RDBMS 术语</h3><p>在我们开始学习MySQL 数据库前，让我们先了解下RDBMS的一些术语：    </p><p><code>数据库</code>: 数据库是一些关联表的集合。.<br><code>数据表</code>: 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。<br><code>列</code>: 一列(数据元素) 包含了相同的数据, 例如邮政编码的数据。<br><code>行</code>：一行（=元组，或记录）是一组相关的数据，例如一条用户订阅的数据。<br><code>冗余</code>：存储两倍数据，冗余可以使系统速度更快。<br><code>主键</code>：主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。<br><code>外键</code>：外键用于关联两个表。<br><code>复合键</code>：复合键（组合键）将多个列作为一个索引键，一般用于复合索引。<br><code>索引</code>：使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。类似于书籍的目录。<br><code>参照完整性</code>: 参照的完整性要求关系中不允许引用不存在的实体。与实体完整性是关系模型必须满足的完整性约束条件，目的是保证数据的一致性。      </p><h3 id="Mysql数据库"><a href="#Mysql数据库" class="headerlink" title="Mysql数据库"></a>Mysql数据库</h3><p>MySQL是一个关系型数据库管理系统，由瑞典MySQL AB公司开发，目前属于Oracle公司。MySQL是一种关联数据库管理系统，关联数据库将数据保存在不同的表中，而不是将所有数据放在一个大仓库内，这样就增加了速度并提高了灵活性。      </p><p>MySQL是开源的，所以你不需要支付额外的费用。<br>MySQL支持大型的数据库。可以处理拥有上千万条记录的大型数据库。<br>MySQL使用标准的SQL数据语言形式。<br>MySQL可以允许于多个系统上，并且支持多种语言。这些编程语言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。<br>MySQL对PHP有很好的支持，PHP是目前最流行的Web开发语言。<br>MySQL支持大型数据库，支持5000万条记录的数据仓库，32位系统表文件最大可支持4GB，64位系统支持最大的表文件为8TB。<br>MySQL是可以定制的，采用了GPL协议，你可以修改源码来开发自己的MySQL系统。      </p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Redis数据库简介</title>
      <link href="database/redis/redis-introduce/"/>
      <url>database/redis/redis-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="Redis-简介"><a href="#Redis-简介" class="headerlink" title="Redis 简介"></a>Redis 简介</h3><p>Redis 是完全开源免费的，遵守BSD协议，是一个高性能的key-value数据库。  </p><p>Redis 与其他 key - value 缓存产品有以下三个特点：  </p><p>Redis支持数据的持久化，可以将内存中的数据保存在磁盘中，重启的时候可以再次加载进行使用。<br>Redis不仅仅支持简单的key-value类型的数据，同时还提供list，set，zset，hash等数据结构的存储。<br>Redis支持数据的备份，即master-slave模式的数据备份。  </p><h3 id="Redis-优势"><a href="#Redis-优势" class="headerlink" title="Redis 优势"></a>Redis 优势</h3><p>性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。<br>丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。<br>原子 – Redis的所有操作都是原子性的，意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务，即原子性，通过MULTI和EXEC指令包起来。<br>丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。  </p><h3 id="Redis与其他key-value存储有什么不同？"><a href="#Redis与其他key-value存储有什么不同？" class="headerlink" title="Redis与其他key-value存储有什么不同？"></a>Redis与其他key-value存储有什么不同？</h3><p>Redis有着更为复杂的数据结构并且提供对他们的原子性操作，这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明，无需进行额外的抽象。  </p><p>Redis运行在内存中但是可以持久化到磁盘，所以在对不同数据集进行高速读写时需要权衡内存，因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是，相比在磁盘上相同的复杂的数据结构，在内存中操作起来非常简单，这样Redis可以做很多内部复杂性很强的事情。同时，在磁盘格式方面他们是紧凑的以追加的方式产生的，因为他们并不需要进行随机访问。</p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于LAMP架构的简单介绍</title>
      <link href="database/lamp-intorduce/"/>
      <url>database/lamp-intorduce/</url>
      
        <content type="html"><![CDATA[<div class="htmledit_views" id="content_views">                                            <p><img alt="" class="has" height="258" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181119082239314.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NqMzQ5NzgxNDc4,size_16,color_FFFFFF,t_70" width="657"></p><p><span style="color:#3399ea;"><strong>一、LAMP架构介绍</strong></span></p><p><strong>&nbsp;&nbsp;&nbsp;</strong>现如今打开浏览器，搜索LAMP关键词，出现大量的关于LAMP的介绍，包括LAMP的一键脚本、LAMP的yum安装、LAMP的编译安装，但是对于一个非开发或非专业人员有可能根据网络参考资源实现LAMP的搭建并成功运行各种服务，也有部分人员完全照搬某些博客知识进行搭建，最后以失败告终，因此抱怨互联网资源不够成熟，其实根本原因并非如此，主要原因如下：</p><ul><li>    <p>初学者对LAMP架构原理不熟悉</p>    </li>    <li>    <p>初学者实验时所用系统和软件版本和某些博客资源并不相同</p>    </li></ul><p>因此导致大量初学者以失败告终,其实只有了解并掌握LAMP的工作原理才能轻松的搭建成功，其次参数的配置都是次要因素，因为互联网上拥有大量的参考资料供查询，下面将逐一介绍</p><p><span style="color:#f33b45;"><strong>&nbsp;&nbsp;&nbsp;</strong>L：很显然L代表Linux系统，但此L需注意系统的版本号，如Centos6.9或Centos7.3；</span></p><p><span style="color:#f33b45;">&nbsp;&nbsp; A：表示apache，在传统行业中，多数采用Apache服务器，因此也很有必要了解学习Apache；</span></p><p><span style="color:#f33b45;">&nbsp;&nbsp; M：表示数据库，多数采用mysql或mariadb，作为专业的数据库工程师需经多年的历练；</span></p><p><span style="color:#f33b45;">&nbsp;&nbsp; P：表示PHP、python、perl等等编程语言。</span></p><p>&nbsp;&nbsp; 在这里注意讲解Linux+apache+mariadb+PHP组合的架构，架构图如下：</p><p><img alt="" class="has" height="398" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181119082310315.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NqMzQ5NzgxNDc4,size_16,color_FFFFFF,t_70" width="558"></p><p>根据上图中访问数据流可知，处理一次动态页面请求，服务器主要经历：<strong>Apache处理请求——通过CGI接口访问PHP的的应用程序——PHP应用程序调用PHP解释器执行PHP代码——PHP程序访问调用数据库——最后给客户做反馈。</strong></p><p>故在LAMP的环境机构中，apache、mariadb和php的主要功能分别如下。</p><p><img alt="" class="has" height="456" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20181119083215117.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NqMzQ5NzgxNDc4,size_16,color_FFFFFF,t_70" width="769"></p><p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#f33b45;"><strong>apache</strong></span>主要实现如下功能：</p><p>&nbsp;&nbsp;&nbsp; 第一：处理http的请求、构建响应报文等自身服务；</p><p>&nbsp;&nbsp;&nbsp; 第二：配置让Apache支持PHP程序的响应（通过PHP模块或FPM）；</p><p>&nbsp;&nbsp;&nbsp; 第三：配置Apache具体处理php程序的方法，如通过反向代理将php程序交给fcgi处理。</p><p>&nbsp;&nbsp;&nbsp;<span style="color:#f33b45;">&nbsp;<strong>mariadb</strong></span>主要实现如下功能：</p><p>&nbsp;&nbsp;&nbsp;&nbsp;第一：提供PHP程序对数据的存储；</p><p>&nbsp;&nbsp;&nbsp;&nbsp;第二：提供PHP程序对数据的读取(通常情况下从性能的角度考虑，尽量实现数据库的读写分离)。</p><p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#f33b45;"><strong>php</strong></span>主要实现如下功能：</p><p>&nbsp;&nbsp;&nbsp;&nbsp;第一：提供apache的访问接口，即CGI或Fast CGI(FPM);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;第二：提供PHP程序的解释器；</p><p>&nbsp;&nbsp;&nbsp;&nbsp;第三：提供mairadb数据库的连接函数的基本环境。</p><p>&nbsp;&nbsp;&nbsp;&nbsp;由此可知，要实现LAMP在配置每一个服务时，安装功能需求进行配置，即可实现LAMP的架构，当然apache、mariadb和php服务都可配置为独立服务，安装在不同服务器之上。</p>                                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> php </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>宇宙最强PHP编辑器:PhpStorm 介绍</title>
      <link href="ide/jetbrains/jetbrains-phpstorm-introduce/"/>
      <url>ide/jetbrains/jetbrains-phpstorm-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>PhpStorm是一个轻量级且便捷的PHPIDE，其旨在提供用户效率，可深刻理解用户的编码，提供智能代码补全，快速导航以及即时错误检查。  </p><h3 id="功能"><a href="#功能" class="headerlink" title="功能"></a>功能</h3><h3 id="智能PHP编辑器"><a href="#智能PHP编辑器" class="headerlink" title="智能PHP编辑器"></a>智能PHP编辑器</h3><p>●　PHP代码补全。<br>●　智能的重复编码检测器。<br>●　PHP重构。<br>●　支持Smarty和PHPDoc。<br>●　支持多语言混合。 [3]     </p><h3 id="JavaScript-编辑器"><a href="#JavaScript-编辑器" class="headerlink" title="JavaScript 编辑器"></a>JavaScript 编辑器</h3><p>●　基于DOM/指定浏览器完成。<br>●　代码导航和用法查找。<br>●　JavaScript 重构。<br>●　JavaScript调试器。 [3]   </p><h3 id="HTML-CSS编辑器"><a href="#HTML-CSS编辑器" class="headerlink" title="HTML/CSS编辑器"></a>HTML/CSS编辑器</h3><p>●　支持HTML5。<br>●　支持Zend编码。<br>●　检验和快速修正。<br>●　显示应用的外观。<br>●　提取嵌入样式。 [3]   </p><h3 id="轻量级IDE"><a href="#轻量级IDE" class="headerlink" title="轻量级IDE"></a>轻量级IDE</h3><p>●　易于安装。<br>●　可在Windows, Mac OS X, Linux上运行。<br>●　项目配置简单-可在任意地方打开代码开始工作。<br>●　性能优先。 [3]   </p><h3 id="智能的环境"><a href="#智能的环境" class="headerlink" title="智能的环境"></a>智能的环境</h3><p>●　可视化PhP单元测试运行期。<br>●　VCS支持SVN, Git, Mercurial等。<br>●　支持FTP和远程文件同步。<br>●　可记录本地修改。<br>●　可视化调试 。<br>●　无需任何配置的调试器。<br>●　支持在PHP，JS，HTML中设置断点。<br>●　观察变量，窗口。<br>●　批量代码分析。<br>●　集成分析器。 [3] </p><h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3><ol><li><p>跨平台。</p></li><li><p>对PHP支持refactor功能。</p></li><li><p>自动生成phpdoc的注释，非常方便进行大型编程。</p></li><li><p>内置支持Zencode。</p></li><li><p>生成类的继承关系图，如果有一个类，多次继承之后，可以通过这个功能查看他所有的父级关系。</p></li><li><p>支持代码重构，方便修改代码。</p></li><li><p>拥有本地历史记录功能（local history功能）。</p></li><li><p>方便的部署，可以直接将代码直接upload到服务器。</p></li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> ide </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>宇宙最强数据库编辑器</title>
      <link href="ide/jetbrains/datagrip/jetbrains-datagrip-introduce/"/>
      <url>ide/jetbrains/datagrip/jetbrains-datagrip-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="idea-DataGrip-使用图解教程"><a href="#idea-DataGrip-使用图解教程" class="headerlink" title="idea DataGrip 使用图解教程"></a>idea DataGrip 使用图解教程</h3><div class="entry">                                                <div class="entry-head">                            <h1 class="entry-title">DataGrip 2018.1.4 功能强大的多引擎数据库管理工具</h1>                            <div class="entry-info">                                                                <a class="nickname" href="https://www.hezibuluo.com/user/hezibuluo">QSQ</a>                                <span class="dot">•</span>                                <span>2019-02-12 21:20</span>                                <span class="dot">•</span>                                <a href="https://www.hezibuluo.com/app/info" rel="category tag">信息管理</a>                                <span class="dot">•</span>                                <a target="_blank" title="点击查看" rel="external nofollow" href="http://www.baidu.com/s?wd=DataGrip 2018.1.4 功能强大的多引擎数据库管理工具">已收录</a>                                                                    <span class="dot">•</span>                                    <span>阅读 3755</span>                                                            </div>                        </div>                        <div class="wpcom_ad_wrap"><!-- PC-文章首尾-800*80 --><ins class="adsbygoogle" style="display:inline-block;width:800px;height:80px" data-ad-client="ca-pub-3975514471171279" data-ad-slot="7149309003" data-adsbygoogle-status="done"><ins id="aswift_0_expand" style="display:inline-table;border:none;height:80px;margin:0;padding:0;position:relative;visibility:visible;width:800px;background-color:transparent;"><ins id="aswift_0_anchor" style="display:block;border:none;height:80px;margin:0;padding:0;position:relative;visibility:visible;width:800px;background-color:transparent;"><iframe width="800" height="80" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_0" name="aswift_0" style="left:0;position:absolute;top:0;border:0px;width:800px;height:80px;"></iframe></ins></ins></ins><script>(adsbygoogle = window.adsbygoogle || []).push({});</script></div>                                                <div class="entry-excerpt">                            <p>DataGrip支持几乎所有主流的关系数据库产品，如DB2、Derby、H2、MySQL、Oracle、PostgreSQL、SQL Server、Sqllite及Sybase等，并且提供了简单易用的界面，开发者上手几乎不会遇到任何困难。Datagrip 2018 是一款数据库管理工具，支持MySQL、Oracle、SQL Server、Sqllite等主流的关系型数据库，除了能执行sql、创建表、创建索引以及导出数据等常用的功能之外，更主要的是Datagrip 2018还能在关键字上有高亮的提示，而且对字段的提示也非常的智能。</p>                        </div>                                                <div class="entry-content clearfix">                            <div><p><noscript><img class="aligncenter" src= "/img/loading.gif" data-lazy-src="https://tvax4.sinaimg.cn/large/006ZzzVqgy1g4qeg9pyfaj30sg0jwq60.jpg" alt="DataGrip 2018.1.4 功能强大的多引擎数据库管理工具" width="1024" height="716" /></noscript><a class="j-wpcom-lightbox" href="https://tvax4.sinaimg.cn/large/006ZzzVqgy1g4qeg9pyfaj30sg0jwq60.jpg" data-group="nogroup" data-id="0" data-index="0"><img class="aligncenter j-lazy" src= "/img/loading.gif" data-lazy-src="https://tvax4.sinaimg.cn/large/006ZzzVqgy1g4qeg9pyfaj30sg0jwq60.jpg" data-original="https://tvax4.sinaimg.cn/large/006ZzzVqgy1g4qeg9pyfaj30sg0jwq60.jpg" alt="DataGrip 2018.1.4 功能强大的多引擎数据库管理工具" width="1024" height="716" style="display: block;"></a></p><h2>应用介绍</h2></div><div id="post-content"><p><span class="wpcom_tag_link"><a href="https://www.hezibuluo.com/tag/datagrip" title="DataGrip" target="_blank">DataGrip</a></span> 是 JetBrains 发布的多引擎数据库环境，支持 MySQL 和 PostgreSQL，Microsoft SQL Server 和 Oracle，Sybase，DB2，SQLite，还有 HyperSQL，Apache Derby 和 H2。DataGrip支持CSV文件导入，JSON和XML文字的支持，正则表达式检查，动态SQL支持，表格完成，键盘布局完成等等。是<span class="wpcom_tag_link"><a href="https://www.hezibuluo.com/tag/mac" title="Mac" target="_blank">Mac</a></span>、windows、Linux平台上不可多得的数据库工具。</p><h3>提供了对主流<span class="wpcom_tag_link"><a href="https://www.hezibuluo.com/tag/%e6%95%b0%e6%8d%ae%e5%ba%93%e7%ae%a1%e7%90%86" title="数据库管理" target="_blank">数据库管理</a></span>系统的访问</h3><p>市场上的重量级产品：Oracle、SQL Server、DB2与Sybase<br>社区流行产品：MySQL、PostgreSQL<br>小众产品：SQLite、Apache Derby、HyperSQL与H2</p><h3>修改数据库对象并自动生成脚本</h3><p>DataGrip提供了一个UI用以执行诸如创建/修改表、管理列、键与索引的操作。可以立即执行生成的代码，也可以在文本编辑器中打开，并直接操作DDL脚本。DataGrip提供了上下文感知的代码完成特性，能够帮助你更快地编写SQL代码。代码完成可以感知到表结构、外键，甚至是正在编辑的代码中所创建的数据库对象。DataGrip可以检测到代码中潜在的Bug，并即时提供最佳的修复建议。它能够立刻让你知道无法解析的对象，并且总能提供问题的修复建议。</p><h3>高效编写SQL并消除重复的编码工作</h3><p>借助于DataGrip，你可以通过代码完成特性更快地编写代码。只需输入数据库对象、标识符或是变量的名字即可，DataGrip会提供一个匹配的列表。DataGrip能够感知到完成JOIN从句所需的依赖，并提供函数与过程所需的参数类型，还可以给出INSERT语句的表结构。DataGrip提供了Live Templates用以生成语句的常见部分，你可以使用默认值，也可以创建新值。</p><h3>在代码间导航并在输入时进行重命名</h3><p>DataGrip能够解析出SQL文件中的对象引用。如果对变量或是别名进行了重命名，那么所有用到他们的地方都会相应地进行重命名。如果在SQL中重命名了数据库对象，实际的数据库中也会进行重命名。DataGrip能够正确解析出SQL代码中所有的引用，并帮助你对其进行重构。</p><p>IDE会展示出对象（表、列等等）的使用，还会在专门的视图中展示出变量。导航工具可以帮助你在编辑器、模式视图等各种上下文中选择对象。</p><h3>处理数据并探索关系</h3><p>你可以通过强大的表编辑器添加、删除、以及克隆数据行。通过过滤文本域可以只查看所需的数据，而无需编写WHERE字句。寻找所需数据的另一种方式是使用文本搜索。如果不知道哪一列包含了你所要寻找的数据，那么文本搜索就是一项非常有用的功能了。可以在文本搜索中使用正则表达式。通过外键数据导航可以转到当前行所引用的数据，反之亦然。</p><p><noscript><img class="aligncenter" src= "/img/loading.gif" data-lazy-src="https://tvax2.sinaimg.cn/large/006ZzzVqgy1g4qegaj1oqj30y50mu762.jpg" alt="DataGrip 2018.1.4 功能强大的多引擎数据库管理工具" width="1229" height="822" /></noscript><a class="j-wpcom-lightbox" href="https://tvax2.sinaimg.cn/large/006ZzzVqgy1g4qegaj1oqj30y50mu762.jpg" data-group="nogroup" data-id="1" data-index="1"><img class="aligncenter j-lazy" src= "/img/loading.gif" data-lazy-src="https://tvax2.sinaimg.cn/large/006ZzzVqgy1g4qegaj1oqj30y50mu762.jpg" data-original="https://tvax2.sinaimg.cn/large/006ZzzVqgy1g4qegaj1oqj30y50mu762.jpg" alt="DataGrip 2018.1.4 功能强大的多引擎数据库管理工具" width="1229" height="822" style="display: block;"></a></p></div><h2>本破解方法适用于所有 JetBrains 系列产品</h2><h3>本方法来自网络</h3><p>原文地址&nbsp;<a href="https://www.hezibuluo.com/go/?url=aHR0cDovL3hpZGVhLm9ubGluZS9zZXJ2ZXJzLmh0bWw=" target="_blank" rel="noopener noreferrer">http://xidea.online</a></p><blockquote><ol><li>打开激活窗口</li><li>选择&nbsp;Activate new license with License server&nbsp;（用license server 激活）</li><li>打开&nbsp;<a href="https://www.hezibuluo.com/go/?url=aHR0cDovL3hpZGVhLm9ubGluZS9zZXJ2ZXJzLmh0bWw=" target="_blank" rel="noopener noreferrer">http://xidea.online/servers.html</a>&nbsp;选择一个&nbsp;Avaliable License Servers</li><li>在&nbsp;License sever address&nbsp;处填入上一步选择的&nbsp;License Servers</li><li>点击&nbsp;Activate&nbsp;进行认证</li><li>done！</li></ol></blockquote><!-- [WPImage2WeiBo queries: 2] --><div class="down">                <div class="comt">                <div class="box-title">文件下载</div>                <div class="box">                <div class="name">                <p>附件：<span>DataGrip 2018.1.4</span></p>                </div>                <div class="box-body">                <p>文件大小：170.4MB</p>                <p>适用平台：Mac</p>                </div>                  <div class="down-button">                <a class="btn btn-primary" href="https://www.hezibuluo.com/down?key=NTAyNQ==" target="_blank" title="DataGrip 2018.1.4"><i class="fa fa-cloud-download" style="margin-right:4px;margin-top:3px"></i> 立即下载</a>                </div>                </div>                <div class="asb1">                <p><!-- 380-140 --><ins class="adsbygoogle" style="display:inline-block;width:380px;height:140px" data-ad-client="ca-pub-3975514471171279" data-ad-slot="2737835716" data-adsbygoogle-status="done"><ins id="aswift_1_expand" style="display:inline-table;border:none;height:140px;margin:0;padding:0;position:relative;visibility:visible;width:380px;background-color:transparent;"><ins id="aswift_1_anchor" style="display:block;border:none;height:140px;margin:0;padding:0;position:relative;visibility:visible;width:380px;background-color:transparent;"><iframe width="380" height="140" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_1" name="aswift_1" style="left:0;position:absolute;top:0;border:0px;width:380px;height:140px;"></iframe></ins></ins></ins><script>     (adsbygoogle = window.adsbygoogle || []).push({});</script>                </p>                </div>                </div>                <div class="down-bloak">                <p>本站资源均来源于网络，只做学习交流使用，版权归原作者所有，请在下载后24小时内自觉删除，若作商业用途，请联系原作者授权，由于未授权或购买发生的侵权行为，与本站无关，本站内容若侵犯了您的权益，请联系本站删除，邮箱：<em><code><a href="https://www.hezibuluo.com/go/?url=bWFpbHRvOm1haWxAaGV6aWJ1bHVvLmNvbQ==" target="_blank" rel="nofollow">mail@hezibuluo.com</a></code></em>                </p>                </div>                </div>                                                        <div class="entry-copyright"><p>原创文章，作者: QSQ，本站资源均来源于网络，仅供学习交流使用，若想体验更多，请支持正版。<br>转载或复制文章时，请注明本文出处及文章链接:  <a href="https://www.hezibuluo.com/5025.html" target="_blank">https://www.hezibuluo.com/5025.html</a></p></div>                        </div>   ]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> datagrip </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>宇宙最强编辑器系列:Jetbrains介绍</title>
      <link href="ide/jetbrains/idea/jetbrains-ide-introduce/"/>
      <url>ide/jetbrains/idea/jetbrains-ide-introduce/</url>
      
        <content type="html"><![CDATA[<div class="markdown-body">            <!-- 欢迎成为极客学院WIKI作者 -->                        <!-- 授权极客学院转载 -->                <p class="author"><a href="https://github.com/judasn" class="reprint-name right-top-img" data-name="点击授权商" target="_blank">Judas.n</a> · 更新于 2018-11-28 11:00:42</p>                        <!-- 内容 -->            <h1>介绍</h1><h2 id="d58a3ddd14ef6536f4a5e42603ae05db">本系列教程介绍</h2><p>本系列教程从 IntelliJ IDEA 的安装、卸载、软件设置、项目配置等各个方面进行讲解。通过本系列教程的学习，也希望你能爱上 IntelliJ IDEA，爱上它的体贴。同时学完本系列教程对于你学习 JetBrains 公司下的其他产品也有好处，其他产品包括：</p><blockquote><ul><li><a rel="nofollow" href="http://www.jetbrains.com/phpstorm/"  title="PhpStorm 主要用于开发 PHP">PhpStorm</a> 主要用于开发 PHP</li><li><a rel="nofollow" href="http://www.jetbrains.com/ruby/"  title="RubyMine 主要用于开发 Ruby">RubyMine</a> 主要用于开发 Ruby</li><li><a rel="nofollow" href="http://www.jetbrains.com/pycharm/"  title="PyCharm 主要用于开发 Python">PyCharm</a> 主要用于开发 Python</li><li><a rel="nofollow" href="http://www.jetbrains.com/objc/"  title="AppCode 主要用于开发 Objective-C">AppCode</a> 主要用于开发 Objective-C / Swift</li><li><a rel="nofollow" href="http://www.jetbrains.com/clion/"  title="CLion 主要用于开发 C/C++">CLion</a> 主要用于开发 C / C++</li><li><a rel="nofollow" href="http://www.jetbrains.com/webstorm/"  title="WebStorm 主要用于开发 JavaScript 等前端技术">WebStorm</a> 主要用于开发 JavaScript、HTML5、CSS3 等前端技术</li><li><a rel="nofollow" href="http://www.jetbrains.com/dbe/"  title="DataGrip 主要用于开发 SQL">DataGrip</a> 主要用于开发 SQL</li><li><a rel="nofollow" href="http://developer.android.com/tools/studio/"  title="Android Studio 主要用于开发 Android">Android Studio</a> 主要用于开发 Android（Google 基于 IntelliJ IDEA 社区版进行迭代所以也姑且算上）</li></ul></blockquote><h2 id="9f5872dbd7bc043f919cbcd1ba189103">IntelliJ IDEA 介绍</h2><blockquote><ul><li>IntelliJ IDEA 官网：<a rel="nofollow" href="https://www.jetbrains.com/idea/" >https://www.jetbrains.com/idea/</a></li></ul></blockquote><p>IntelliJ IDEA 在 2015 年 06 月官网主页是这样介绍自己的：</p><blockquote><p>Excel at enterprise, mobile and web development with Java, Scala and Groovy, with all the latest modern technologies and frameworks available out of the box.</p></blockquote><p>简明翻译：IntelliJ IDEA 主要用于支持 Java、Scala、Groovy 等语言的开发工具，同时具备支持目前主流的技术和框架，擅长于企业应用、移动应用和 Web 应用的开发。</p><p>IntelliJ IDEA 对自己的定义是很清晰的，对于新人来讲可能还不太理解，可能还会有误会，认为它博而不精，但是对于老用户来讲应该是非常认可上面这句话的。通过下面功能表格，新人对于 IntelliJ IDEA 所具备的功能会有一个新的认识。</p><p>如果用一句话来形容 IntelliJ IDEA，我会说：<strong>IntelliJ IDEA 是目前所有 IDE 中最具备沉浸式的 JVM IDE，没有之一</strong>。 </p><h2 id="d1a66d0e4565515013c548a757c046d3">IntelliJ IDEA 主要功能介绍</h2><blockquote><ul><li>语言支持上：</li></ul></blockquote><table><thead><tr><th style="text-align: left;">安装插件后支持</th><th style="text-align: left;">SQL类</th><th style="text-align: left;">基本JVM</th></tr></thead><tbody><tr><td style="text-align: left;">PHP</td><td style="text-align: left;">PostgreSQL</td><td style="text-align: left;">Java</td></tr><tr><td style="text-align: left;">Python</td><td style="text-align: left;">MySQL</td><td style="text-align: left;">Groovy</td></tr><tr><td style="text-align: left;">Ruby</td><td style="text-align: left;">Oracle</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">Scala</td><td style="text-align: left;">SQL Server</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">Kotlin</td><td style="text-align: left;"></td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">Clojure</td><td style="text-align: left;"></td><td style="text-align: left;"></td></tr></tbody></table><blockquote><ul><li>其他支持：</li></ul></blockquote><table><thead><tr><th style="text-align: left;">支持的框架</th><th style="text-align: left;">额外支持的语言代码提示</th><th style="text-align: left;">支持的容器</th></tr></thead><tbody><tr><td style="text-align: left;">Spring MVC</td><td style="text-align: left;">HTML5</td><td style="text-align: left;">Tomcat</td></tr><tr><td style="text-align: left;">GWT</td><td style="text-align: left;">CSS3</td><td style="text-align: left;">TomEE</td></tr><tr><td style="text-align: left;">Vaadin</td><td style="text-align: left;">SASS</td><td style="text-align: left;">WebLogic</td></tr><tr><td style="text-align: left;">Play</td><td style="text-align: left;">LESS</td><td style="text-align: left;">JBoss</td></tr><tr><td style="text-align: left;">Grails</td><td style="text-align: left;">JavaScript</td><td style="text-align: left;">Jetty</td></tr><tr><td style="text-align: left;">Web Services</td><td style="text-align: left;">CoffeeScript</td><td style="text-align: left;">WebSphere</td></tr><tr><td style="text-align: left;">JSF</td><td style="text-align: left;">Node.js</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">Struts</td><td style="text-align: left;">ActionScript</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">Hibernate</td><td style="text-align: left;"></td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">Flex</td><td style="text-align: left;"></td><td style="text-align: left;"></td></tr></tbody></table><p>上面特性只是 IntelliJ IDEA 的冰山一角，而且这个还不是 IntelliJ IDEA 最重要的地方，IntelliJ IDEA 最重要的特性就是人性化、智能，后面学习你会慢慢接触到。</p><h2 id="31366c9276e6126c25c0490d9cfef87f">更多官方学习信息</h2><blockquote><ul><li>IntelliJ IDEA 主要特性介绍 1：<a rel="nofollow" href="https://www.jetbrains.com/idea/features/" >https://www.jetbrains.com/idea/features/</a></li><li>IntelliJ IDEA 主要特性介绍 2：<a rel="nofollow" href="https://www.jetbrains.com/idea/features/editions_comparison_matrix.html" >https://www.jetbrains.com/idea/features/editions_comparison_matrix.html</a></li><li>官方快速入门：<a rel="nofollow" href="http://confluence.jetbrains.com/display/IntelliJIDEA/Quick+Start" >http://confluence.jetbrains.com/display/IntelliJIDEA/Quick+Start</a></li><li>官方在线帮助文档：<a rel="nofollow" href="http://www.jetbrains.com/idea/webhelp/getting-help.html" >http://www.jetbrains.com/idea/webhelp/getting-help.html</a></li><li>官方 wiki：<a rel="nofollow" href="http://wiki.jetbrains.net/intellij" >http://wiki.jetbrains.net/intellij</a></li></ul></blockquote><h2 id="0ce963d1052f0ba1689eed01429a26af">更多官方资讯跟踪途径</h2><blockquote><ul><li>官方博客：<a rel="nofollow" href="http://blog.jetbrains.com/idea/" >http://blog.jetbrains.com/idea/</a></li><li>IntelliJ IDEA 官方 community：<a rel="nofollow" href="https://intellij-support.jetbrains.com/hc/en-us/community/topics" >https://intellij-support.jetbrains.com/hc/en-us/community/topics</a></li><li>IntelliJ IDEA 官方 issue：<a rel="nofollow" href="https://youtrack.jetbrains.com/issues/IDEA" >https://youtrack.jetbrains.com/issues/IDEA</a></li><li>YouTube：<a rel="nofollow" href="https://www.youtube.com/user/intellijideavideo" >https://www.youtube.com/user/intellijideavideo</a></li><li>Twitter：<a rel="nofollow" href="https://twitter.com/IntelliJIDEA" >https://twitter.com/IntelliJIDEA</a></li><li>Facebook：<a rel="nofollow" href="https://www.facebook.com/IntelliJIDEA" >https://www.facebook.com/IntelliJIDEA</a></li><li>JetBrains 新浪微博：<a rel="nofollow" href="http://www.weibo.com/u/3220313942" >http://www.weibo.com/u/3220313942</a></li><li>JetBrains Google+：<a rel="nofollow" href="https://plus.google.com/+jetbrains" >https://plus.google.com/+jetbrains</a></li><li>IntelliJ IDEA Google+：<a rel="nofollow" href="https://plus.google.com/+intellijidea" >https://plus.google.com/+intellijidea</a></li></ul></blockquote>        </div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>宇宙最强Java编辑器</title>
      <link href="ide/jetbrains/idea/jetbrains-idea-introduce/"/>
      <url>ide/jetbrains/idea/jetbrains-idea-introduce/</url>
      
        <content type="html"><![CDATA[<div id="article_content" class="article_content clearfix">                                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">                                        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">                <div class="htmledit_views" id="content_views">                                            <h1><a name="t0"></a><strong>前言：IntelliJ IDEA</strong></h1><p>如果说IntelliJ IDEA是一款现代化智能开发工具的话，Eclipse则称得上是<code>石器时代</code>的东西了。其实笔者也是一枚从Eclipse转IDEA的探索者，随着近期的不断开发实践和调试，逐步体会到这款智能IDE带来的巨大开发便利，在强大的插件功能支持下，诸如对Git和Maven的支持简直让人停不下来，各种代码提示，包括JS更是手到擒来，最终不得不被这款神奇的IDE所折服。为了让身边更多的小伙伴参与进来，决定写下这篇文章，与君共享。(*^_^*)</p><p>高级传送门：<a href="https://link.jianshu.com/?t=https%3A%2F%2Fwww.jetbrains.com%2Fidea%2Fdownload%2F%23section%3Dwindows" rel="nofollow" data-token="a10d260e3f5f408735a67237789d53d3">IntelliJ IDEA 官网下载 - Ultimate 终极版</a></p><p>激活方法： 安装完成后 选择License&nbsp; 输入 http://intellij.mandroid.cn</p><h1><a name="t1"></a><a name="t1"></a><strong>正文：IntelliJ IDEA 使用教程</strong></h1><h3><a name="t2"></a><a name="t2"></a><strong>1. IDEA VS Eclipse 核心术语比较</strong></h3><p><strong>&nbsp; &nbsp; 由下图可见：</strong>两者最大的转变就在于工作空间概念的转变，并且在IDEA当中，Project和&nbsp; Module是作为两个不同的概念，对项目结构是重要意义的，这也恰恰是许多IDEA初学者觉得困扰的地方。</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-1f60e92b9a8d5559.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/648"></p><h4><a name="t3"></a><a name="t3"></a>&nbsp; &nbsp; 1.1 为什么要取消工作空间？</h4><p>&nbsp; &nbsp; &nbsp; &nbsp; 答：&nbsp;<strong>简单来说，IDEA不需要设置工作空间，因为每一个Project都具备一个工作空间！！<u>对于每一个IDEA的项目工程（Project）而言，它的每一个子模块（Module）都可以使用独立的JDK和MAVEN</u></strong><u>。</u>这对于传统项目迈向新项目的重构添加了极大的便利性，这种多元化的灵活性正是Eclipse所缺失的，因为开始Eclipse在初次使用时已经绑死了工作空间。</p><p>&nbsp; &nbsp; 1.2 此外，很多新手都会问，为什么IDEA里面的子工程要称为Module ？</p><p>&nbsp; &nbsp; &nbsp; &nbsp; 答：其实就是模块化的概念，作为聚合工程亦或普通的根目录，它称之为Project，而下面的子工程称为模块，每一个子模块之间可以相关联，也可以没有任何关联。</p><h3><a name="t4"></a><a name="t4"></a><strong>2. 当前项目配置VS 默认配置&nbsp;&nbsp;</strong></h3><p>&nbsp; &nbsp; 2.1 为什么有了当前项目配置，还需要默认配置呢？</p><p><strong>&nbsp; &nbsp; 答：<u>因为IDEA没有工作空间的概念，所以每个新项目（Project）都需要设置自己的JDK和MAVEN等相关配置，</u></strong>这样虽然提高了灵活性，但是却要为每个新项目都要重新配置，这显然不符合我们的预期。在这个背景下，<u><strong>默认配置给予当前项目配置提供了Default选项</strong></u>，问题自然就迎刃而解了。</p><p>&nbsp; &nbsp; 2.2 初始化步骤</p><p>&nbsp; &nbsp; &nbsp; 打开默认配置：顶部导航栏 -&gt; File -&gt; Other Settings -&gt; Default Settings /ProjectStructs&nbsp;</p><p>&nbsp; &nbsp; &nbsp; 打开当前配置：顶部导航栏 -&gt; File -&gt; Settings / ProjectStructs</p><p><strong>&nbsp; &nbsp; &nbsp;示例图：</strong></p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-ac73a71f4046699e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/494"></p><p>如果当前项目想覆盖默认配置，直接在Settins/Project Structure设置即可。</p><blockquote><p>=============================================</p><p>接下来，来看看IDEA如何快速搭建Java开发环境！！</p><p>=============================================</p></blockquote><h3><a name="t5"></a><a name="t5"></a>3. 全局JDK（默认配置）</h3><p>&nbsp; 具体步骤：顶部工具栏&nbsp; File -&gt;Other Settins -&gt; Default Project Structure -&gt; SDKs -&gt; JDK</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 示例： 根据下图步骤设置JDK目录，最后点击OK保存。</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-fa02a9132d9aaee2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/683"></p><p>PS：同理，当前项目在Project Structure可为工程和各模块设置喜欢的JDK版本。</p><h3><a name="t6"></a><a name="t6"></a>4. 全局Maven（默认配置）</h3><p>具体步骤：顶部工具栏&nbsp; File -&gt;Other Settings -&gt; Default Settings -&gt; Build &amp; Tools -&gt; Maven</p><p>&nbsp; &nbsp; &nbsp; 示例： 理论上只要配置了Maven主目录即可，实际开发推荐采用User Settins file .</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-c847845f860324be.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700"></p><p>PS:为了方便查阅,推荐在Settings配置好本地仓库. 例如D:\mvnrepository</p><h3><a name="t7"></a><a name="t7"></a>5. 版本控制Git/Svn （默认配置）</h3><p>具体步骤：顶部工具栏&nbsp; File -&gt;Other Settings -&gt; Default Settings -&gt; Version Control -&gt; Git</p><p>&nbsp; &nbsp; &nbsp; 示例： IDEA默认集成了对Git/Svn的支持&nbsp; 直接设置执行程序，右边Test提示成功即可。</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 部分小伙伴反馈说无法找到svn.exe，解决方法：重装SVN，配置项重新选择command line client tools 即可。</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-9bbaa622cf3daeed.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700"></p><p>PS: IDEA内置的Git插件灰常好用，尤其是解决冲突性的代码。另外Git客户端推荐SourceTree。</p><h3><a name="t8"></a><a name="t8"></a>6. 自动导包和智能移除 （默认配置）</h3><p>具体步骤：顶部工具栏&nbsp; File -&gt;Other Settings -&gt; Default Settings -&gt; Auto Import</p><p>&nbsp; &nbsp; &nbsp; 说明：&nbsp;<strong>在网上看到很多人在提问IDEA为什么不能优化导包而Eclipse可以，</strong></p><p><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 所以特意抽出来跟大家分享IDEA如何优化导包。</strong></p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-d66b1318a29ab251.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700"></p><h3><a name="t9"></a><a name="t9"></a>&nbsp; 7. Tomcat Server（当前项目配置）&nbsp;</h3><p>很多小伙伴刚开始都找不到Tomcat的配置，其实很简单，Tomcat或者Jetty这些都是部署的容器，自然会联想到Deployment ，打开部署配置，可以看到应用服务器的配置。</p><p>配置Tomcat方法： File -&gt; Settings -&gt; Deployment -&gt; Application Servers -&gt; Tomcat Server&nbsp;&nbsp;</p><p>具体配置方法，如下图：</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-4d628299a415e63d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700"></p><h2><a name="t10"></a><a name="t10"></a>IDEA 必备小技能&nbsp;</h2><p>为了提升开发效率，撸主贴心为大家准备以下实用指数五颗星的小技巧：</p><h3><a name="t11"></a><a name="t11"></a>8. 自动编译</h3><p>具体步骤：顶部工具栏&nbsp; File -&gt;Other Settings -&gt; Default Settings -&gt; Auto Import</p><p>说明：开启自动编译之后，结合Ctrl+Shift+F9 会有热更新效果。</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-e10620f9da31fe9c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700"></p><h4><a name="t12"></a><a name="t12"></a>自动编译（Runtime）</h4><p>具体步骤： 敲击 Ctrl + Shift + Alt + /&nbsp; 然后进入Registry ，找到compiler.automake.allow.when.app.running ，然后勾选上。</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-0734034dd7995cf4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/371"></p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-3a4d633c2c0496f5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700"></p><h3><a name="t13"></a><a name="t13"></a>9. 取消大小写敏感</h3><p>具体步骤：</p><p>File | Settings | Editor | General | Code Completion Case | Sensitive Completion = None</p><p>取消大小敏感，在编写代码的时候，代码的自动提示将更加全面和丰富。</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-60b6ee65a7b778a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700"></p><h3><a name="t14"></a><a name="t14"></a>10. 调整字体类型和字体大小</h3><p>默认的白色背景和细小的字体会影响大家的编码体验，这里特意提供了调整代码窗的快捷配置。打开配置，搜索Font，然后再Font可以调整字体类型，Size可以调整字体大小</p><h3><a name="t15"></a><a name="t15"></a>10. 将快捷键设置为跟Eclipse一样</h3><p>很多人可能并不习惯IDEA的快捷键，为了方便，这里我们将快捷键设置为跟 Eclipse一样。</p><p>具体步骤: File -&gt; Settings -&gt; Keymap - &gt; 选择Eclipse .</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-de1b7cb998e21a2d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700"></p><p>从Eclipse转过来的小伙伴 可以放心使用</p><h3><a name="t16"></a><a name="t16"></a>11. 打开常用工具栏</h3><p>具体步骤：顶部导航栏 - View -&gt; 勾选 Toolbar &amp; Tool Buttons</p><p>如下图所示：</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-575c85658a9b06fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/534"></p><h3><a name="t17"></a><a name="t17"></a>12. 打开Maven神器（强烈推荐！）</h3><p>具体步骤：右侧直接点击 Maven Project 管理插件 ，记得先打开常用工具栏，详见8.3。</p><p>如下图所示： 还在Eclipse使用Update命令苦苦挣扎的童鞋，请火速尝试此款插件，能给你带来前所未有的愉快感！！</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-c6aca3ce3f7cb954.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/429"></p><h3><a name="t19"></a><a name="t19"></a>13. 懒人必备快捷键</h3><p>&nbsp;</p><p><strong>1. 按【鼠标中键】快速打开智能提示，取代alt+enter 。</strong></p><p>File-&gt;Settings-&gt; Keymap-&gt; 搜索 Show Intention Actions -&gt; 添加快捷键为鼠标中键。</p><p><strong>2. 按【F2】快速修改文件名，告别双手操作。</strong></p><p>File-&gt;Settings-&gt; Keymap-&gt; 搜索 Rename -&gt; 将快捷键设置为F2 。</p><p><strong>3. 按【F3】直接打开文件所在目录，浏览一步到位。</strong></p><p>File-&gt;Settings-&gt; Keymap-&gt; 搜索 Show In Explorer -&gt; 将快捷键设置为F3 。</p><p><strong>4. 按【Ctrl+右键】直接打开实现类，方便开发查询。</strong></p><p>File-&gt;Settings-&gt; Keymap-&gt; 搜索 implementation-&gt;&nbsp; Add Mouse Shortcut 将快捷键设置为Ctrl+ 鼠标右键。</p><p>&nbsp;</p><h3><a name="t20"></a><a name="t20"></a><strong>14. 重度强迫症患者</strong></h3><p><strong>1.取消大小写敏感，让自动完成更齐全！&nbsp;&nbsp;</strong></p><p>File | Settings | Editor | General | Code Completion Case | Sensitive Completion = None。</p><p><strong>2.自动隐藏注释，让源码阅读更为清爽！&nbsp;</strong></p><p>File -&gt; Settings -&gt; Editor -&gt; General -&gt; Code Folding -&gt;&nbsp; Documentation comments 勾选。</p><p>如何想快速一键打开全部注释，则单击鼠标右键，选择Folding -&gt; Expand Doc comments 。</p><p><strong>3. Maven自动下载源码包，告别反编译，直接上源码注释！！</strong></p><p>File | Settings | Build, Execution, Deployment | Build Tools | Maven | Importing</p><p>将Automatically Download&nbsp; 的 Source 勾上。</p><p>&nbsp;</p><h3><a name="t21"></a><a name="t21"></a>15. IDEA十问十答</h3><p>&nbsp; &nbsp;&nbsp;<strong>（1）如何打开本地工程/已存在的工程？</strong></p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;答：点击File -&gt; Open 打开 工程文件夹即可，注意先配置好JDK、Maven等基础配置。</p><p><strong>&nbsp; &nbsp;（2）IDEA如何删除项目工程？</strong></p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 答：问这个问题的Coder真的好可爱啊哈哈，很肯定的回答你，不需要删，</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 点击File-&gt; Close Project 即可快速关闭当前项目； 示例：</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;什么？你还是想要干掉整个目录？那也阔以，右键Show In Explorer ，删掉文件夹&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;即可。不过笔者建议还是直接Close关掉就好啦，万一以后用得上呢，你说呢？</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-8fa3622b2e764134.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/274"></p><p><strong>&nbsp; &nbsp;（3）如何在单个窗口打开多个Maven工程啊？</strong></p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 答：随便新建一个文件夹，然后将工程都扔进去，使用IDEA打开这个文件夹。</p><p><strong>&nbsp; &nbsp;（4）如何为当前项目工程添加多个模块啊？</strong></p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;答： 对着工程右键 -&gt; 选择New -&gt; Module -&gt; 通常选择Spring Initializr&nbsp; ，如图：</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-64822a874d368f32.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/563"></p><p>新增模块</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://upload-images.jianshu.io/upload_images/8069210-b1aa086b58e093c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/304"></p><p>多模块工程</p>                                    </div>                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> idea </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>宇宙最强python编辑器</title>
      <link href="ide/jetbrains/pycharm/jetbrains-pycharm-introduce/"/>
      <url>ide/jetbrains/pycharm/jetbrains-pycharm-introduce/</url>
      
        <content type="html"><![CDATA[<div id="content_views" class="markdown_views prism-atom-one-dark">                    <!-- flowchart 箭头图标 勿删 -->                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                    </svg>                                            <p>本文由Markdown语法编辑器编辑完成。</p><h2 id="1-pycharm的介绍"><a name="t0"></a>1. PyCharm的介绍：</h2><p>PyCharm是一款Python的IDE的编辑工具，它是由Jetbrains出品的产品。之前我在做Web项目，前端撰写JavaScript代码时，就是用的他们公司出品的前端开发神器WebStorm。因此，也一直对他们的产品很感兴趣，而且，如果是同一个公司的产品，在很多设置上都是相同的，也可以减少一些学习成本。</p><p>PyCharm的官网地址为: <br><a href="http://www.jetbrains.com/pycharm/" rel="nofollow" data-token="502ed7dede3c2bb27616c18a0a6f9ddb">http://www.jetbrains.com/pycharm/</a></p><h2 id="2-pycharm的基本设置"><a name="t1"></a>2. PyCharm的基本设置</h2><p>PyCharm的快捷键： <br><a href="http://www.cnblogs.com/zhangpengshou/p/3555767.html" rel="nofollow" data-token="bc9904113cb322e461924d574b93aba2">http://www.cnblogs.com/zhangpengshou/p/3555767.html</a></p><h2 id="3-pycharm安装第三方库时的方法"><a name="t2"></a>3. PyCharm安装第三方库时的方法</h2><h3 id="31-python的包管理器pip"><a name="t3"></a>3.1 <strong>Python的包管理器：pip</strong></h3><p>应用Python的包管理器，下载Python图像处理的库scikit-image</p><h3 id="32-python第三方包的列表"><a name="t4"></a>3.2 <strong>Python第三方包的列表：</strong></h3><p><a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/" rel="nofollow" data-token="acc3af145fbd8b5091f5fb9c4c547721">http://www.lfd.uci.edu/~gohlke/pythonlibs/</a></p><h3 id="33-pythonscikit-image"><a name="t5"></a>3.3 <strong>Python：scikit-image.</strong></h3><p>Python中与图像处理相关的第三方包scikit-image，见文末的首页截图。 <br><a href="http://scikit-image.org/" rel="nofollow" data-token="316a458bdb2bfd016fd4ef840bc390bf">http://scikit-image.org/</a></p><h3 id="34-pythonscikit-learn"><a name="t6"></a>3.4 <strong>Python：scikit-learn.</strong></h3><p>Python中与机器学习，数据挖掘，深度学习有关的第三方包：scikit-learn**,它包含了机器学习中常见的：Classification、Regression、 Clustering、Dimensionality reduction、Model selection、Preprocessing等基本的类别，，见文末的首页截图。 <br><a href="http://scikit-learn.org/stable/" rel="nofollow" data-token="f863b780d124a258f7feead02a0c5df6">http://scikit-learn.org/stable/</a></p><h2 id="4-参考链接"><a name="t7"></a>4. 参考链接：</h2><ol><li>Python-Matplotlib安装及简单使用 <br><a href="http://www.open-open.com/lib/view/open1393488232380.html" rel="nofollow" data-token="0fa2442f6f97527c35760710b2891b3b">http://www.open-open.com/lib/view/open1393488232380.html</a></li><li> <br><a href="http://blog.csdn.net/yang6464158/article/details/18546871#comments" rel="nofollow" data-token="7ab5e80fa82099f160f17dc6bc487e14">http://blog.csdn.net/yang6464158/article/details/18546871#comments</a></li><li>PyCharm的教程系列： <br><a href="http://blog.csdn.net/chenggong2dm/article/category/6137682" rel="nofollow" data-token="4c8b681f9684f0f198f9b266532a7d25">http://blog.csdn.net/chenggong2dm/article/category/6137682</a></li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> pycharm </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于WebStrom在Chrome中打开本地js文件解决方案</title>
      <link href="ide/jetbrains/webstrom/webstrom-port/"/>
      <url>ide/jetbrains/webstrom/webstrom-port/</url>
      
        <content type="html"><![CDATA[<h3 id="方式一-本地文件打开"><a href="#方式一-本地文件打开" class="headerlink" title="方式一:本地文件打开"></a>方式一:本地文件打开</h3><p>在点击webstorm右上角的浏览器图标时,按住shift键(以文件协议打开html文件)</p><h3 id="方式二-配置webstorm中的本地服务器设置"><a href="#方式二-配置webstorm中的本地服务器设置" class="headerlink" title="方式二:配置webstorm中的本地服务器设置"></a>方式二:配置webstorm中的本地服务器设置</h3><p>localhost是可以引用的， </p><p><code>http://localhost:63342</code> </p><p>指向的是你创建的项目的根目录的上一级目录，是webstorm创建项目时配置的服务器</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> webstrom </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>一行命令带你安装mongodb(deepin系统下)</title>
      <link href="database/deepin-install-mongodb/"/>
      <url>database/deepin-install-mongodb/</url>
      
        <content type="html"><![CDATA[<h3 id="一行命令安装mongodb"><a href="#一行命令安装mongodb" class="headerlink" title="一行命令安装mongodb"></a>一行命令安装mongodb</h3><p><code>sudo apt-get install mongodb</code></p><h3 id="详细的在下面"><a href="#详细的在下面" class="headerlink" title="详细的在下面"></a>详细的在下面</h3><div class="blog-content-box"><article class="baidu_pl">            <div id="article_content" class="article_content clearfix">                                <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">                                    <div id="content_views" class="markdown_views">                <!-- flowchart 箭头图标 勿删 -->                <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                    <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                </svg>                                        <p>安装 <br>下载地址：<a href="https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.0.tgz" rel="nofollow" data-token="5491b390828b119075d28645562c9a0c">https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.0.tgz</a>（或者到官网上下载别的版本）</p><p>完成下载后，把软件包移动到软件安装的目录下，我这里是/usr/local/。</p><p>解压：tar -zxvf mongodb-linux-x86_64-2.6.0.tgz（权限不够，要加sudo，下同）</p><p>更改安装目录：mv mongodb-linux-x86_64-2.6.0.tgz mongodb</p><p>创建mongodb数据库存放路径：mkdir -p /data/db</p><p>创建mongodb数据库日志存放路径：mkdir -p /usr/local/mongodb/log/（存放在安装路径下）</p><p>启动服务</p><pre class="prettyprint" name="code"><code class="hljs brainfuck has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-comment">启动mongodb服务：/usr/local/mongodb/bin/mongod</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">dbpath=/data/db</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">logpath=/usr/local/mongodb/log/mongodb</span><span class="hljs-string">.</span><span class="hljs-comment">log</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">logappend</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">port</span> <span class="hljs-comment">27017</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">fork（若出现错误，可能是权限不够）</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">dbpath</span> <span class="hljs-comment">数据库路径(数据文件)</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">logpath</span> <span class="hljs-comment">数据库日志文件路径</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">port</span> <span class="hljs-comment">启用端口号</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">fork</span> <span class="hljs-comment">在后台运行</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">auth</span> <span class="hljs-comment">是否需要验证权限登录(用户名和密码)</span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><p>设置mongodb <br>添加安装路径到path中：</p><pre class="prettyprint" name="code"><code class="hljs ruby has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-variable">$ </span>vim /etc/profile添加一下代码到文件的最后一行，并保存<span class="hljs-symbol">:</span>export <span class="hljs-constant">PATH</span>=<span class="hljs-variable">$PATH</span><span class="hljs-symbol">:/usr/local/mongodb/bin</span>使设置生效：source /etc/profile进入控制台：mongo（在任意位置）<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p>设置mongodb开机自启： <br>编辑mongodb配置文件，设置启动参数：vim /usr/local/mongodb/mongodb.conf（没有就新建一个）</p><p>加入以下参数并保存：</p><pre class="prettyprint" name="code"><code class="hljs ini has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-setting">dbpath=<span class="hljs-value">/data/db #数据库路径</span></span><span class="hljs-setting">port=<span class="hljs-value"><span class="hljs-number">27017</span> #端口号</span></span><span class="hljs-setting">fork=<span class="hljs-value"><span class="hljs-keyword">true</span> #设置后台运行</span></span><span class="hljs-setting">logappend=<span class="hljs-value"><span class="hljs-keyword">true</span></span></span><span class="hljs-setting">shardsvr=<span class="hljs-value"><span class="hljs-keyword">true</span></span></span><span class="hljs-setting">pidfilepath=<span class="hljs-value">/usr/local/mongodb/mongo.pid</span></span><span class="hljs-setting">logpath=<span class="hljs-value">/usr/local/mongodb/log/mongodb.log #日志输出文件路径</span></span><span class="hljs-setting">directoryperdb=<span class="hljs-value"><span class="hljs-keyword">true</span></span></span><span class="hljs-setting">auth=<span class="hljs-value"><span class="hljs-keyword">false</span> #关闭认证</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre><p>打开命令行，输入mongo，即可验证。</p>                                    </div>                <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-095d4a0b23.css" rel="stylesheet">                    </div>    </article>    </div>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mongodb </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Deepin 下安装 LAMP</title>
      <link href="database/deepin-lamp/"/>
      <url>database/deepin-lamp/</url>
      
        <content type="html"><![CDATA[<p>ubuntu/deepin linux 下使用 apt-get 安装所需套的软件 LAMP</p><h3 id="1-安装-apacache2"><a href="#1-安装-apacache2" class="headerlink" title="1. 安装 apacache2"></a>1. 安装 apacache2</h3><p><code>apt-get install apache2</code><br>配置文件：/etc/apache2/apache2.conf    </p><p><code>service apache2 start</code></p><p><code>service apache2 stop</code></p><p><code>service apache2 restart</code></p><h3 id="2-安装-mysql"><a href="#2-安装-mysql" class="headerlink" title="2. 安装 mysql"></a>2. 安装 mysql</h3><p><code>sudo apt-get install mysql-server mysql-client</code></p><p>测试：<code>mysql -u root -p  XXX</code></p><p><code>service mysql start</code></p><p><code>service mysql stop</code></p><p><code>service mysql restart</code></p><p>注释：安装时提示无法安装等信息，原因是没有更新源（apt-get install update）</p><h3 id="3-安装-php7"><a href="#3-安装-php7" class="headerlink" title="3. 安装 php7"></a>3. 安装 php7</h3><p><code>sudo apt-get install php7.0</code></p><h3 id="4-安装其他模块"><a href="#4-安装其他模块" class="headerlink" title="4.安装其他模块"></a>4.安装其他模块</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install libapache2-mod-php7.0</span><br><span class="line">sudo apt-get install php7.0-mysql</span><br></pre></td></tr></table></figure><h3 id="5-安装Redis"><a href="#5-安装Redis" class="headerlink" title="5 安装Redis"></a>5 安装Redis</h3><p><code>apt-get install redis-server</code><br>redis 启动 <code>redis-server</code><br>redis 客户端 <code>redis-cli</code></p><p>PHP 还需要安装一些扩展 还没装好 后期待续 ,如有不足之处多多指教</p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> php </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>一行命令带你安装mysql(deepin系统下)</title>
      <link href="database/mysql/deepin-install-mysql/"/>
      <url>database/mysql/deepin-install-mysql/</url>
      
        <content type="html"><![CDATA[<p><code>sudo apt-get install mysql-server mysql-client</code></p><p>测试：<code>mysql -u root -p XXX</code></p><p><code>service mysql start</code></p><p><code>service mysql stop</code></p><p><code>service mysql restart</code></p><p>注释：安装时提示无法安装等信息，原因是没有更新源（apt-get install update）</p>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>一行命令带你安装redis(deepin系统下)</title>
      <link href="database/redis/deepin-install-redis/"/>
      <url>database/redis/deepin-install-redis/</url>
      
        <content type="html"><![CDATA[<h3 id="1-安装Redis服务"><a href="#1-安装Redis服务" class="headerlink" title="1.安装Redis服务"></a>1.安装Redis服务</h3><p><code>apt-get install redis-server</code></p><h3 id="2-启动服务"><a href="#2-启动服务" class="headerlink" title="2.启动服务"></a>2.启动服务</h3><p><code>/etc/init.d/redis-server start</code></p><h3 id="3-连接服务"><a href="#3-连接服务" class="headerlink" title="3.连接服务"></a>3.连接服务</h3><p><code>redis-cli</code></p><h3 id="详细内容"><a href="#详细内容" class="headerlink" title="详细内容"></a>详细内容</h3><div class="blog-content-box">    <div class="article-header-box">        <div class="article-header">       <article class="baidu_pl">            <div id="article_content" class="article_content clearfix">                                            <div class="article-copyright">            <span class="creativecommons">            <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">                </a></span>        </div>                                        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">                            <div id="content_views" class="markdown_views">        <!-- flowchart 箭头图标 勿删 -->        <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">            <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>        </svg>                                <h2 id="nosql和redis的介绍"><a name="t0"></a>NoSQL和redis的介绍</h2><p>传统的关系型数据库难以支持当下“三高”的互联网环境，而NoSQL能在高并发，高扩展等方面体现较强的优势，具体体现有以下几点：</p><ul><li>易扩展性</li><li>高负载型（用空间换时间）</li><li>灵活多样的数据类型</li><li>高可用性</li></ul><p>redis是NoSQL中的一个比较典型的非关系型数据库，其常用在以下几个方面：</p><ul><li>缓存机制（最常用）</li><li>在线好友列表</li><li>任务队列，比如秒杀活动等</li><li>应用排行榜</li></ul><p>接下来将记录我在deepin系统下，安装以及使用redis的步骤。</p><h2 id="安装c的编译环境"><a name="t1"></a>安装C的编译环境</h2><p>由于redis是C语言开发的，所以对redis进行编译的之前，需要安装C的编译环境。 <br>在控制台中输入：</p><pre class="prettyprint" name="code"><code class="hljs lasso has-numbering" onclick="mdcp.signin(event)" style="position: unset;">sudo apt<span class="hljs-attribute">-get</span> install gcc g<span class="hljs-subst">++</span> <span class="hljs-attribute">-y</span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h2 id="解压redis压缩文件"><a name="t2"></a>解压redis压缩文件</h2><p>首先下载一个redis的压缩文件，解压到/usr/local目录下</p><pre class="prettyprint" name="code"><code class="hljs lasso has-numbering" onclick="mdcp.signin(event)" style="position: unset;">tar <span class="hljs-attribute">-xvf</span> redis<span class="hljs-subst">-</span><span class="hljs-number">3.0</span><span class="hljs-number">.0</span><span class="hljs-built_in">.</span>tar<span class="hljs-built_in">.</span>gz <span class="hljs-attribute">-C</span> /usr/<span class="hljs-built_in">local</span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h2 id="编译redis"><a name="t3"></a>编译redis</h2><p>进入到redis解压的目录下</p><pre class="prettyprint" name="code"><code class="hljs bash has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-built_in">cd</span> /usr/local/redis-<span class="hljs-number">3.3</span>.<span class="hljs-number">0</span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p>使用make命令编译redis</p><pre class="prettyprint" name="code"><code class="hljs bash has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-built_in">sudo</span> make<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h2 id="安装"><a name="t4"></a>安装</h2><p>在redis解压的目录（/usr/local/redis-3.3.0）下，使用如下命令安装redis到/usr/local/redis中</p><pre class="prettyprint" name="code"><code class="hljs bash has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-built_in">sudo</span> make PREFIX=/usr/local/redis install<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p>其中<code>PREFIX=/usr/local/redis</code>就是制定安装的路径</p><h2 id="拷贝配置文件"><a name="t5"></a>拷贝配置文件</h2><p>将/usr/local/redis-3.0.0中的redis.conf拷贝到安装目录/usr/local/redis/bin中</p><pre class="prettyprint" name="code"><code class="hljs avrasm has-numbering" onclick="mdcp.signin(event)" style="position: unset;">sudo <span class="hljs-keyword">cp</span> redis<span class="hljs-preprocessor">.conf</span> /usr/local/redis/bin/<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p>用vim修改配置文件中的<code>daemonize no</code>为<code>daemonize yes</code> <br>注意，该<code>redis.conf</code>可能为只读文件，需要用sudo命令来打开vim进行编辑</p><pre class="prettyprint" name="code"><code class="hljs bash has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-built_in">sudo</span> vim /usr/local/redis/bin/redis.conf<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h2 id="启动redis"><a name="t6"></a>启动redis</h2><p>启动方式分为前端启动和后端启动</p><h4 id="前端启动">前端启动</h4><p>直接运行bin/redis-server <br>首先进入<code>/usr/local/redis/bin</code>目录，然后输入<code>./redis-server</code> <br>启动后的效果如下： <br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171106121600303?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDIyOTIxNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="前端启动效果图" title=""> <br>前端模式启动的缺点是启动完成之后，不能再进行其他操作，如果操作必须使用ctrl+c，同时redis-server程序结束，不推荐这种开启方式。</p><h4 id="后端启动">后端启动</h4><p>进入redis目录，然后输入<code>./redis-server ./redis.conf</code>，即可启动redis服务端， <br>然后输入<code>./redis-cli</code>即可进入客户端进行操作</p><h2 id="退出redis"><a name="t7"></a>退出redis</h2><p>从客户端进入redis之后，输入<code>exit</code>退出</p>                                    </div>                <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-095d4a0b23.css" rel="stylesheet">                    </div>    </article>    </div>]]></content>
      
      
      
        <tags>
            
            <tag> database </tag>
            
            <tag> redis </tag>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
            <tag> nosql </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于deepin系统的各种坑</title>
      <link href="linux/deepin-bug/"/>
      <url>linux/deepin-bug/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p><a href="https://ttk1907.gitee.io/">ttk1907的博客</a>中说到:<br><a href="https://ttk1907.gitee.io/2019/09/21/xiongdihui-deepin/">Deepin系统天坑</a></p><p><a href="https://victorfengming.gitee.io/">victor的博客</a>中的<br><a href="https://victorfengming.gitee.io/linux/deepin-bluetooth/">关于deepin系统不能识别蓝牙设备问题的完美解决方案</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>程序员必须掌握哪些算法？</title>
      <link href="unclass/programmers-master/"/>
      <url>unclass/programmers-master/</url>
      
        <content type="html"><![CDATA[<h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>身为一个程序员,我们需要掌握很多的算法<br>那么熟练掌握这些算法，到底可以为身为程序员的我们带来什么呢？</p><h3><b>提升代码效率</b></h3><p>比如，现在让你实现这样一个功能：给你一些有序的数字，动态地查找目标数字。实现这一功能的方法有很多种，当面临不同情况的时候，我们需要使用不同的方法。</p><ol><li>查找频率很低时，对于每一次查询，暴力从前向后遍历，每次查询的复杂度为 <code>O(N)</code>，能解决问题。</li><li>当查找频率很高时，对有序数字使用二分查找，每次查询复杂度为 <code>O(logN)</code>。或者使用哈希表，每次查询的复杂度为 <code>O(1)</code>。</li><li>如果数字非常多存不进内存里，可以使用 <code>B树</code> 的思路来优化查询。</li><li>当引入密集的插入操作，查询不太密集的时候，可以使用 <code>LSM树</code> 的思想完成这一功能。</li></ol><p>如果你熟知各种基础算法，那么你就可以很容易地针对不同的场景找到合适的解决方案，并且将它们变成代码，以提升程序的效率。而不是遇事不决，先上暴力，虽然解决了问题，但是在时间与空间上还有很多不足。</p><h3><b>提升能力、借鉴思路、获得启发</b></h3><p>通过学习这些算法，可以提升我们在计算机方面的能力：抽象建模能力、逻辑思维能力等，并且积累一些解决问题的基本思路：折半、倍增、贪心、分治等。</p><p>现实中的问题都大相径庭，但是我们通过将其抽象并建模之后，会发现问题的本质是相似的，我们往往可能从某一个基础算法中获得启发，从而高效地解决问题。而达到这一境界，就要求我们首先对基础算法能非常了解，并达到熟练运用，融会贯通的地步。</p><p>所以，即使过了公司面试这一关，算法对于程序员来说依然是非常重要的。熟练掌握算法，将是你职场晋升路上的一把利刃。还是那句话，奔着求职、面试、晋升的小伙伴，刷 <a href="https://link.zhihu.com/?target=http%3A//leetcode-cn.com/" class=" wrap external" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">力扣</a> 拿到你的 Dream Offer，走向人生巅峰！</p><h3>对于算法的学习的平台，只要关注以下三个维度来进行选择：</h3><ul><li>第一、能够学习算法的原理，在动态规划之后的很多算法，都需要花时间去理解，需要有一个学习的过程。所以，学习算法的过程无论是边学边做还是简单的学习，最好可以附带一定的教学功能。</li><li>第二、可以对算法进行练习的在线测评系统 (OnlineJudge)。如何选择一个适合自己的 OJ 去练习？力扣君认为首先要看其支持的语言种类与检索功能，另外是否有定期的原创题目，原创比赛。是的，原创非常重要！（敲小黑板咯！）</li><li>第三、针对第二点，明确进行算法练习的目的，单纯为了提升算法能力还是在提升的同时也想为自己的技术面试做准备。</li></ul><h3>给大家推荐几个算法学习的网站：</h3><p>一、力扣 Leetcode（<a href="http://leetcode-cn.com)/">http://leetcode-cn.com）</a></p><p>二、Github （<a href="https://github.com/">https://github.com</a>)</p><p>三、Topcoder（<a href="http://topcoder.com/">http://topcoder.com</a>)</p><p>四、CourseraCoursera  Online Courses &amp; Credentials by Top Educators. Join for Free</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> summer </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于Sass和less的奇妙故事</title>
      <link href="front/sass/diff-sass-less/"/>
      <url>front/sass/diff-sass-less/</url>
      
        <content type="html"><![CDATA[<article class="_2rhmJa"><div class="image-package"><img src= "/img/loading.gif" data-lazy-src="http://img0.imgtn.bdimg.com/it/u=861104756,4244471114&amp;fm=26&amp;gp=0.jpg" data-original-src="http://img0.imgtn.bdimg.com/it/u=861104756,4244471114&amp;fm=26&amp;gp=0.jpg" data-image-index="0" style="cursor: zoom-in;"><div class="image-caption"></div></div><h3>起步</h3><p>首先sass和less都是css的预编译处理语言，他们引入了mixins，参数，嵌套规则，运算，颜色，名字空间，作用域，JavaScript赋值等 加快了css开发效率,当然这两者都可以配合gulp和grunt等前端构建工具使用</p><p>sass和less主要区别:在于实现方式 less是基于JavaScript的在客户端处理 所以安装的时候用npm，sass是基于ruby所以在服务器处理。</p><p>很多开发者不会选择LESS因为JavaScript引擎需要额外的时间来处理代码然后输出修改过的CSS到浏览器。关于这个有很多种方式，我选择的是只在开发环节使用LESS。一旦我完成了开发，我就复制然后粘贴LESS输出的到一个压缩器，然后到一个单独的CSS文件来替代LESS文件。另一个选择是使用LESS.app来编译和压缩你的LESS文件。两个选择都将最小化你的样式输出，从而避免由于用户的浏览器不支持JavaScript而可能引起的任何问题。尽管这不大可能，但终归是有可能的</p><h3>LESS详细</h3><p>首先扩展文件名的格式是 xxx.less</p><p>在此推荐大家在练习环节可以用</p><pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>less.js<span class="token punctuation">"</span></span><span class="token attr-name">...</span><span class="token punctuation">&gt;</span></span> 这种方式编译less<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>但在实际项目中 还是用命令行的 lessc xxx.less&gt;xxx.css 方式然后引入编译后的css文件 这样减少在运行时上面出现的问题</p><pre class="line-numbers  language-cpp"><code class="  language-cpp">//安装lessnpm install -g less<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><h5>变量</h5><pre class="line-numbers  language-java"><code class="  language-java">@变量名<span class="token operator">:</span>值<span class="token annotation punctuation">@width</span>：<span class="token number">100</span>px<span class="token punctuation">;</span><span class="token punctuation">.</span>box<span class="token punctuation">&#123;</span>    width<span class="token operator">:</span><span class="token annotation punctuation">@width</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><h5>混合</h5><pre class="line-numbers  language-java"><code class="  language-java">定义classa 然后可以将classa引入到classb中<span class="token punctuation">.</span><span class="token function">classa</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>    width<span class="token operator">:</span><span class="token annotation punctuation">@width</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><p><span class="token punctuation">.</span>classb<span class="token punctuation">&#123;</span><br>    <span class="token punctuation">.</span><span class="token function">classa</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><h5>嵌套规则</h5><pre class="line-numbers  language-undefined"><code class="  language-undefined">父级&#123;    子集&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><h5>函数和运算</h5><pre class="line-numbers  language-ruby"><code class="  language-ruby">可以将值计算<span class="token variable">@the</span><span class="token operator">-</span>border<span class="token punctuation">:</span> <span class="token number">1</span>px<span class="token punctuation">;</span><span class="token variable">@base</span><span class="token operator">-</span>color<span class="token punctuation">:</span> <span class="token comment">#111;</span><span class="token variable">@red</span><span class="token punctuation">:</span>        <span class="token comment">#842210;</span><p><span class="token comment">#header &#123;</span><br>  color<span class="token punctuation">:</span> <span class="token variable">@base</span><span class="token operator">-</span>color <span class="token operator"><em></span> <span class="token number">3</span><span class="token punctuation">;</span><br>  border<span class="token operator">-</span>left<span class="token punctuation">:</span> <span class="token variable">@the</span><span class="token operator">-</span>border<span class="token punctuation">;</span><br>  border<span class="token operator">-</span>right<span class="token punctuation">:</span> <span class="token variable">@the</span><span class="token operator">-</span>border <span class="token operator"></em></span> <span class="token number">2</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><br><span class="token comment">#footer &#123; </span><br>  color<span class="token punctuation">:</span> <span class="token variable">@base</span><span class="token operator">-</span>color <span class="token operator">+</span> <span class="token comment">#003300;</span><br>  border<span class="token operator">-</span>color<span class="token punctuation">:</span> desaturate<span class="token punctuation">(</span><span class="token variable">@red</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token operator">%</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><h3>SASS详细</h3><p>首件扩展文件名的格式是 xxx.scss 或者是 xxx.sass</p><p>使用方法: sass xxx.scss xxx.css</p><h5>编译风格：</h5><pre class="line-numbers  language-undefined"><code class="  language-undefined">nested:嵌套缩进的css代码，默认expanded:没有缩紧的,扩展的css代码campact:简介格式的css代码compressed:压缩后的css代码(生产环境)<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><p>使用的时候　sass --style compressed xxx.sass xxx.css</p><h5>监听目录</h5><pre class="line-numbers  language-cpp"><code class="  language-cpp">sass --watch xxx.scss:xxx.css //监听文件sass --watch scsspath:csspath //监听文件夹<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><h5>变量</h5><pre class="line-numbers  language-ruby"><code class="  language-ruby">$变量名<span class="token punctuation">:</span>值<span class="token variable">$width</span>：<span class="token number">100</span>px<span class="token punctuation">;</span><p><span class="token punctuation">.</span>box<span class="token punctuation">&#123;</span><br>    width<span class="token punctuation">:</span><span class="token variable">$width</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span></p><p>如果变量包含字符串则写在 <span class="token comment">#&#123;&#125;之中</span><br><span class="token variable">$c</span><span class="token symbol">:color</span><span class="token punctuation">;</span></p><p><span class="token punctuation">.</span>box<span class="token punctuation">&#123;</span><br>    border<span class="token operator">-</span><span class="token comment">#&#123;$c&#125;:red;</span><br><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><h5>嵌套计算</h5><p>less和sass嵌套相同，计算同理</p><h5>继承</h5><p>同less混合相同 定义classa 然后再classb可饮用classa值</p><pre class="line-numbers  language-java"><code class="  language-java"><span class="token comment">//使用方法 定义classa </span><span class="token punctuation">.</span>classb<span class="token punctuation">&#123;</span>    <span class="token annotation punctuation">@extend</span> <span class="token punctuation">.</span>classa<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><h5>Mixin</h5><p>即重用代码块</p><pre class="line-numbers  language-cpp"><code class="  language-cpp">//使用方法先用@mixin命令定义一个代码块@mixin left(参数1，参数2)&#123;    float:left;    margin-left:10px;&#125;//使用@include调用刚刚定义的代码块.box&#123;    @inclidu left(参数1，参数2);&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h5>颜色函数 lighten(颜色，百分比)</h5><h5>插入文件</h5><pre class="line-numbers  language-cpp"><code class="  language-cpp">@import命令插入外部文件 .scss和css都可<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h5>条件语句</h5><pre class="line-numbers  language-bash"><code class="  language-bash">//@if 可以用来判断 @else 则是配套<p>.box&#123;<br>    @if 1+1&gt;1 &#123;width:100px;&#125;@else &#123;<br>        width:200px;<br>    &#125;<br>&#125;<br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><h5>循环语句</h5><pre class="line-numbers  language-bash"><code class="  language-bash">//@for @while @each<p>@for $i from 1 to 10&#123;<br>    border-#&#123;$i&#125;&#123;<br>        border:#&#123;$i&#125;px solid red;<br>    &#125;<br>&#125;</p><p>//@while<br>$i:6;<br>@while $i&gt;0&#123;<br>    .item-#&#123;$i&#125;&#123;<br>        width:2em*$i;<br>    &#125;<br>    $i:$i-2;<br>&#125;</p><p>//@each<br>    @each $member in a, b, c, d &#123;<br>　　　　.#&#123;$member&#125; &#123;<br>　　　　　　background-image: url(“/image/#&#123;$member&#125;.jpg”);<br>　　　　&#125;<br>　　&#125;<br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><h5>自定义函数</h5><pre class="line-numbers  language-css"><code class="  language-css"><span class="token atrule"><span class="token rule">@function</span> <span class="token function">name</span><span class="token punctuation">(</span>$n<span class="token punctuation">)</span></span><span class="token punctuation">&#123;</span>    <span class="token atrule"><span class="token rule">@return</span> $n*2<span class="token punctuation">;</span></span><span class="token punctuation">&#125;</span><p><span class="token selector">.box</span><span class="token punctuation">&#123;</span><br>    <span class="token property">width</span><span class="token punctuation">:</span><span class="token function">name</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><h3>总结</h3><p>总体来说sass和less都有各自的好处，这要根据每个开发者的习惯和爱好来使用，都可提高开发效率，当然还有stylus等工具，因为目前未使用过所以不做评判，个人比较倾向sass，至于比较，两者都有其优缺点，如果你开发环境中并没有ruby 并且你不想安装ruby 你就可以使用less，如果你觉得sass的语法你更倾向并且你安装了ruby 你就可以使用sass。总之工具不重要，码出一手好代码才是真理。</p></article>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sass、LESS 和 Stylus区别总结</title>
      <link href="front/sass/diff-sass-stylus/"/>
      <url>front/sass/diff-sass-stylus/</url>
      
        <content type="html"><![CDATA[<div id="content_views" class="markdown_views">                    <!-- flowchart 箭头图标 勿删 -->                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                    </svg>                                            <p>CSS 预处理器技术已经非常的成熟了，而且也涌现出了越来越多的 CSS 的预处理器框架。本文便总结下 Sass、Less CSS、Stylus这三个预处理器的区别和各自的基本语法。</p><h2 id="1什么是-css-预处理器"><a name="t0"></a>1.什么是 CSS 预处理器</h2><p>CSS 预处理器是一种语言用来为 CSS 增加一些编程的的特性，无需考虑浏览器的兼容性问题，例如你可以在 CSS 中使用变量、简单的程序逻辑、函数等等在编程语言中的一些基本技巧，可以让CSS 更见简洁，适应性更强，代码更直观等诸多好处。</p><h2 id="2基本语法区别"><a name="t1"></a>2.基本语法区别:</h2><p>在使用 CSS 预处理器之前最重要的是理解语法，幸运的是基本上大多数预处理器的语法跟 CSS 都差不多。</p><p>首先 Sass 和 Less 都使用的是标准的 CSS 语法，因此如果可以很方便的将已有的 CSS 代码转为预处理器代码，默认 Sass 使用 .sass 扩展名，而 Less 使用 .less 扩展名。</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-comment">/* style.scss or style.less */</span><span class="hljs-tag">h1</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#0982C1</span></span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre><p>这是一个再普通不过的，不过 Sass 同时也支持老的语法，就是不包含花括号和分号的方式：</p><pre class="prettyprint" name="code"><code class="hljs rsl has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-comment">/* style.sass */</span>h1  <span class="hljs-keyword">color</span>: <span class="hljs-preprocessor">#0982c1</span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre><p>而 Stylus 支持的语法要更多样性一点，它默认使用 .styl 的文件扩展名，下面是 Stylus 支持的语法：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-comment">/* style.styl */</span><span class="hljs-tag">h1</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#0982C1</span></span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-comment">/* omit brackets */</span><span class="hljs-tag">h1</span>  <span class="hljs-tag">color</span>: <span class="hljs-id">#0982C1</span>;<span class="hljs-comment">/* omit colons and semi-colons */</span><span class="hljs-tag">h1</span>  <span class="hljs-tag">color</span> <span class="hljs-id">#0982C1</span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><p>可以在同一个样式单中使用不同的变量，例如下面的写法也不会报错：</p><pre class="prettyprint" name="code"><code class="hljs rsl has-numbering" onclick="mdcp.signin(event)" style="position: unset;">h1 &#123;  <span class="hljs-keyword">color</span> <span class="hljs-preprocessor">#0982c1</span>&#125;h2  font-size: <span class="hljs-number">1.2</span>em<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h2 id="3变量"><a name="t2"></a>3.变量</h2><p><strong>1. sass：</strong></p><p>Sass让人们受益的一个重要特性就是它为css引入了变量。你可以把反复使用的css属性值 定义成变量，然后通过变量名来引用它们，而无需重复书写这一属性值。</p><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.signin(event)" style="position: unset;">     sass变量必须是以$开头的，然后变量和值之间使用冒号（：）隔开，和css属性是一样的，例如：<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;">$<span class="hljs-tag">maincolor</span> : <span class="hljs-id">#092873</span>;$<span class="hljs-tag">siteWidth</span> : 1024<span class="hljs-tag">px</span>;$<span class="hljs-tag">borderStyle</span> : <span class="hljs-tag">dotted</span>;<span class="hljs-tag">body</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> $maincolor</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"> <span class="hljs-number">1</span>px $borderStyle $mainColor</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">max-width</span>:<span class="hljs-value"> $siteWidth</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre><p><strong>2.less css ：</strong></p><p>在less文件中，当一个值需要反复使用时，可以通过@符号定义变量。已经被赋值的变量以及其他的常量（如像素、颜色等）都可以参与运算。</p><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.signin(event)" style="position: unset;"> Less css中变量都是用@开头的，其余与sass都是一样的，例如：<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-at_rule">@<span class="hljs-keyword">maincolor</span> : #<span class="hljs-number">092873</span></span>;<span class="hljs-at_rule">@<span class="hljs-keyword">siteWidth</span> : <span class="hljs-number">1024</span>px</span>;<span class="hljs-at_rule">@<span class="hljs-keyword">borderStyle</span> : dotted</span>;<span class="hljs-tag">body</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> @maincolor</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"> <span class="hljs-number">1</span>px @borderStyle @mainColor</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">max-width</span>:<span class="hljs-value"> @siteWidth</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre><p><strong>3.stylus：</strong></p><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.signin(event)" style="position: unset;"> stylus对变量是没有任何设定的，可以是以$开头，或者任何的字符，而且与变量之间可以用冒号，空格隔开， 但是在stylus中不能用@开头，例如：    <div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><pre class="prettyprint" name="code"><code class="hljs rsl has-numbering" onclick="mdcp.signin(event)" style="position: unset;">maincolor = <span class="hljs-preprocessor">#092873</span>siteWidth = <span class="hljs-number">1024</span>pxborderStyle = dottedbody   <span class="hljs-keyword">color</span> maincolor  border <span class="hljs-number">1</span>px borderStyle mainColor  <span class="hljs-built_in">max</span>-width siteWidth<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre><p>以上三种写法都如同一下这种css：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-tag">body</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#092873</span></span></span>;  <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"> <span class="hljs-number">1</span>px dotted <span class="hljs-hexcolor">#092873</span></span></span>;  <span class="hljs-rule"><span class="hljs-attribute">max-width</span>:<span class="hljs-value"> <span class="hljs-number">1024</span>px</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p>这样做的好处也是显而易见的，在修改多处相同颜色的时候，这时就只需要修改变量值即可。</p><h2 id="4嵌套"><a name="t3"></a>4.嵌套</h2><p>如果我们需要在CSS中相同的 parent 引用多个元素，这将是非常乏味的，你需要一遍又一遍地写 parent。例如：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-tag">div</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">10</span>px</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-tag">div</span> <span class="hljs-tag">nav</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">height</span>:<span class="hljs-value"> <span class="hljs-number">25</span>px</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-tag">div</span> <span class="hljs-tag">nav</span> <span class="hljs-tag">a</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#0982C1</span></span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-tag">div</span> <span class="hljs-tag">nav</span> <span class="hljs-tag">a</span><span class="hljs-pseudo">:hover</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">text-decoration</span>:<span class="hljs-value"> underline</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><p>如果用 CSS 预处理器，就可以少写很多单词，而且父子节点关系一目了然，并且sass，Less，stylus都支持下面这样的写法，且都是相同的：</p><pre class="prettyprint" name="code"><code class="hljs scss has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-comment">//scss style //----------------------------------- </span><span class="hljs-tag">nav</span> &#123;     <span class="hljs-tag">ul</span> &#123;        <span class="hljs-attribute">margin</span><span class="hljs-value">: <span class="hljs-number">0</span>;</span>        <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">0</span>;</span>     &#125;     <span class="hljs-tag">li</span> &#123;        <span class="hljs-attribute">display</span><span class="hljs-value">: inline-block;</span>     &#125;     <span class="hljs-tag">a</span> &#123;        <span class="hljs-attribute">display</span><span class="hljs-value">: block;</span>        <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">6</span>px <span class="hljs-number">12</span>px;</span>        <span class="hljs-attribute">text-decoration</span><span class="hljs-value">: none;</span>     &#125; &#125;<span class="hljs-comment">//css style //----------------------------------- </span><span class="hljs-tag">nav</span> <span class="hljs-tag">ul</span> &#123;     <span class="hljs-attribute">margin</span><span class="hljs-value">: <span class="hljs-number">0</span>;</span>     <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">0</span>;</span>     <span class="hljs-attribute">list-style</span><span class="hljs-value">: none;</span> &#125; <span class="hljs-tag">nav</span> <span class="hljs-tag">li</span> &#123;     <span class="hljs-attribute">display</span><span class="hljs-value">: inline-block;</span> &#125; <span class="hljs-tag">nav</span> <span class="hljs-tag">a</span> &#123;     <span class="hljs-attribute">display</span><span class="hljs-value">: block;</span>     <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">6</span>px <span class="hljs-number">12</span>px;</span>     <span class="hljs-attribute">text-decoration</span><span class="hljs-value">: none;</span> &#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li></ul></pre><p>这样做是非常方便的，也很直观。</p><h2 id="5运算符"><a name="t4"></a>5.运算符</h2><p>在 CSS 预处理器中还是可以进行样式的计算如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-tag">body</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> (<span class="hljs-number">14</span>px/<span class="hljs-number">2</span>)</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">top</span>:<span class="hljs-value"> <span class="hljs-number">50</span>px + <span class="hljs-number">100</span>px</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">right</span>:<span class="hljs-value"> <span class="hljs-number">80</span> * <span class="hljs-number">10</span>%</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p>在sass，Less与stylus中都是可以这样做的。</p><h2 id="6颜色函数"><a name="t5"></a>6.颜色函数</h2><p>CSS 预处理器一般都会内置一些颜色处理函数用来对颜色值进行处理，例如加亮、变暗、颜色梯度等。</p><p><strong>1.sass的颜色处理函数：</strong></p><pre class="prettyprint" name="code"><code class="hljs mel has-numbering" onclick="mdcp.signin(event)" style="position: unset;">lighten(<span class="hljs-variable">$color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>; darken(<span class="hljs-variable">$color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>;  saturate(<span class="hljs-variable">$color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>;   desaturate(<span class="hljs-variable">$color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>;grayscale(<span class="hljs-variable">$color</span>);  complement(<span class="hljs-variable">$color</span>); invert(<span class="hljs-variable">$color</span>); mix(<span class="hljs-variable">$color1</span>, <span class="hljs-variable">$color2</span>, <span class="hljs-number">50</span><span class="hljs-variable">%)</span>; <div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre><p>实例如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;">$<span class="hljs-tag">color</span>: <span class="hljs-id">#0982C1</span>;<span class="hljs-tag">h1</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background</span>:<span class="hljs-value"> $color</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"> <span class="hljs-number">3</span>px solid <span class="hljs-function">darken($color, <span class="hljs-number">50</span>%)</span></span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p><strong>2.Less css颜色处理函数：</strong></p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-tag">lighten</span>(<span class="hljs-at_rule">@<span class="hljs-keyword">color,</span> <span class="hljs-number">10</span>%)</span>; <span class="hljs-tag">darken</span>(<span class="hljs-at_rule">@<span class="hljs-keyword">color,</span> <span class="hljs-number">10</span>%)</span>;  <span class="hljs-tag">saturate</span>(<span class="hljs-at_rule">@<span class="hljs-keyword">color,</span> <span class="hljs-number">10</span>%)</span>;  <span class="hljs-tag">desaturate</span>(<span class="hljs-at_rule">@<span class="hljs-keyword">color,</span> <span class="hljs-number">10</span>%)</span>; <span class="hljs-tag">spin</span>(<span class="hljs-at_rule">@<span class="hljs-keyword">color,</span> <span class="hljs-number">10</span>)</span>; <span class="hljs-tag">spin</span>(<span class="hljs-at_rule">@<span class="hljs-keyword">color,</span> -<span class="hljs-number">10</span>)</span>; <span class="hljs-tag">mix</span>(<span class="hljs-at_rule">@<span class="hljs-keyword">color1,</span> @color2)</span>;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre><p>示例如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-at_rule">@<span class="hljs-keyword">color:</span> #<span class="hljs-number">0982</span>C1</span>;<span class="hljs-tag">h1</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background</span>:<span class="hljs-value"> @color</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"> <span class="hljs-number">3</span>px solid <span class="hljs-function">darken(@color, <span class="hljs-number">50</span>%)</span></span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p><strong>3.Stylus颜色处理函数：</strong></p><pre class="prettyprint" name="code"><code class="hljs mel has-numbering" onclick="mdcp.signin(event)" style="position: unset;">lighten(<span class="hljs-keyword">color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>; darken(<span class="hljs-keyword">color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>;  saturate(<span class="hljs-keyword">color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>;  desaturate(<span class="hljs-keyword">color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>; <div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre><p>示例如下;</p><pre class="prettyprint" name="code"><code class="hljs rsl has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-keyword">color</span> = <span class="hljs-preprocessor">#0982C1 </span>h1  background <span class="hljs-keyword">color</span>  border <span class="hljs-number">3</span>px solid darken(<span class="hljs-keyword">color</span>, <span class="hljs-number">50</span>%)<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre><h2 id="7导入-import"><a name="t6"></a>7.导入 (Import)</h2><p>很多 CSS 开发者对导入的做法都不太感冒，因为它需要多次的 HTTP 请求。但是在 CSS 预处理器中的导入操作则不同，它只是在语义上包含了不同的文件，但最终结果是一个单一的 CSS 文件，如果你是通过 @ import “file.css”; 导入 CSS 文件，那效果跟普通的 CSS 导入一样。</p><p><strong>注意：</strong>导入文件中定义的混入、变量等信息也将会被引入到主样式文件中，因此需要避免它们互相冲突。 <br>例如： <br>1.css:</p><pre class="prettyprint" name="code"><code class="hljs scss has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-comment">//1.css</span><span class="hljs-comment">/* file.&#123;type&#125; */</span><span class="hljs-tag">body</span> &#123;  <span class="hljs-attribute">background</span><span class="hljs-value">: <span class="hljs-hexcolor">#000</span>;</span>&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p>2.XXX:</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-at_rule">@ import <span class="hljs-string">"1.css"</span></span>;<span class="hljs-at_rule">@ import <span class="hljs-string">"file.&#123;type&#125;"</span></span>;<span class="hljs-tag">p</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#092873</span></span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><p>最终生成的 CSS：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-at_rule">@ import <span class="hljs-string">"1.css"</span></span>;<span class="hljs-tag">body</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#000</span></span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-tag">p</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#092873</span></span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre><h2 id="8继承"><a name="t7"></a>8.继承</h2><p>当我们需要为多个元素定义相同样式的时候，我们可以考虑使用继承的做法.</p><p><strong>1.sass：</strong> <br>sass可通过@extend来实现代码组合声明，使代码更加优越简洁。</p><pre class="prettyprint" name="code"><code class="hljs scss has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-class">.message</span> &#123;  <span class="hljs-attribute">border</span><span class="hljs-value">: <span class="hljs-number">1</span>px solid <span class="hljs-hexcolor">#ccc</span>;</span>  <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">10</span>px;</span>  <span class="hljs-attribute">color</span><span class="hljs-value">: <span class="hljs-hexcolor">#333</span>;</span>&#125;<span class="hljs-class">.success</span> &#123;  <span class="hljs-at_rule">@<span class="hljs-keyword">extend</span><span class="hljs-preprocessor"> .message</span>;</span>  <span class="hljs-attribute">border-color</span><span class="hljs-value">: green;</span>&#125;<span class="hljs-class">.error</span> &#123;  <span class="hljs-at_rule">@<span class="hljs-keyword">extend</span><span class="hljs-preprocessor"> .message</span>;</span>  <span class="hljs-attribute">border-color</span><span class="hljs-value">: red;</span>&#125;<span class="hljs-class">.warning</span> &#123;  <span class="hljs-at_rule">@<span class="hljs-keyword">extend</span><span class="hljs-preprocessor"> .message</span>;</span>  <span class="hljs-attribute">border-color</span><span class="hljs-value">: yellow;</span>&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li></ul></pre><p><strong>2.Less css：</strong></p><p>但是在这方面 Less 表现的稍微弱一些，更像是混入写法：</p><pre class="prettyprint" name="code"><code class="hljs scss has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-class">.message</span> &#123;  <span class="hljs-attribute">border</span><span class="hljs-value">: <span class="hljs-number">1</span>px solid <span class="hljs-hexcolor">#ccc</span>;</span>  <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">10</span>px;</span>  <span class="hljs-attribute">color</span><span class="hljs-value">: <span class="hljs-hexcolor">#333</span>;</span>&#125;<span class="hljs-class">.success</span> &#123;  <span class="hljs-class">.message</span>;  <span class="hljs-attribute">border-color</span><span class="hljs-value">: green;</span>&#125;<span class="hljs-class">.error</span> &#123;  <span class="hljs-class">.message</span>;  <span class="hljs-attribute">border-color</span><span class="hljs-value">: red;</span>&#125;<span class="hljs-class">.warning</span> &#123;  <span class="hljs-class">.message</span>;  <span class="hljs-attribute">border-color</span><span class="hljs-value">: yellow;</span>&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li></ul></pre><p>上面两种写法其最终呈现的css样式都如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-class">.message</span>, <span class="hljs-class">.success</span>, <span class="hljs-class">.error</span>, <span class="hljs-class">.warning</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"> <span class="hljs-number">1</span>px solid <span class="hljs-hexcolor">#cccccc</span></span></span>;  <span class="hljs-rule"><span class="hljs-attribute">padding</span>:<span class="hljs-value"> <span class="hljs-number">10</span>px</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#333</span></span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.success</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">border-color</span>:<span class="hljs-value"> green</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.error</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">border-color</span>:<span class="hljs-value"> red</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.warning</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">border-color</span>:<span class="hljs-value"> yellow</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li></ul></pre><p>.message的样式将会被插入到相应的你想要继承的选择器中，但需要注意的是优先级的问题。</p><h2 id="9mixins混入"><a name="t8"></a>9.Mixins（混入）</h2><p>Mixins 有点像是函数或者是宏，当某段 CSS 经常需要在多个元素中使用时，可以为这些共用的 CSS 定义一个 Mixin，然后只需要在需要引用这些 CSS 地方调用该 Mixin 即可。</p><p><strong>1.Sass 的混入语法：</strong></p><p>sass中可用mixin定义一些代码片段，且可传参数，方便日后根据需求调用。比如说处理css3浏览器前缀：</p><pre class="prettyprint" name="code"><code class="hljs scss has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-at_rule">@<span class="hljs-keyword">mixin</span><span class="hljs-preprocessor"> error</span>($borderWidth:<span class="hljs-preprocessor"> 2px</span>) &#123;</span>  <span class="hljs-attribute">border</span><span class="hljs-value">: $borderWidth solid <span class="hljs-hexcolor">#F00</span>;</span>  <span class="hljs-attribute">color</span><span class="hljs-value">: <span class="hljs-hexcolor">#F00</span>;</span>&#125;<span class="hljs-class">.generic-error</span> &#123;  <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">20</span>px;</span>  <span class="hljs-attribute">margin</span><span class="hljs-value">: <span class="hljs-number">4</span>px;</span>  <span class="hljs-at_rule">@<span class="hljs-preprocessor"> include</span><span class="hljs-preprocessor"> error</span>();</span> <span class="hljs-comment">//这里调用默认 border: 2px solid #F00;</span>&#125;<span class="hljs-class">.login-error</span> &#123;  <span class="hljs-attribute">left</span><span class="hljs-value">: <span class="hljs-number">12</span>px;</span>  <span class="hljs-attribute">position</span><span class="hljs-value">: absolute;</span>  <span class="hljs-attribute">top</span><span class="hljs-value">: <span class="hljs-number">20</span>px;</span>  <span class="hljs-at_rule">@<span class="hljs-preprocessor"> include</span><span class="hljs-preprocessor"> error</span>(<span class="hljs-number">5</span>px);</span> <span class="hljs-comment">//这里调用 border:5px solid #F00;</span>&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li></ul></pre><p><strong>2.Less CSS 的混入语法：</strong> <br>less也支持带参数的混合以及有默认参数值的混合，如下面的例子所示：</p><pre class="prettyprint" name="code"><code class="hljs scss has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-class">.error</span>(<span class="hljs-at_rule">@borderWidth:<span class="hljs-preprocessor"> 2px</span>) &#123;</span>  <span class="hljs-attribute">border</span><span class="hljs-value">: @borderWidth solid <span class="hljs-hexcolor">#F00</span>;</span>  <span class="hljs-attribute">color</span><span class="hljs-value">: <span class="hljs-hexcolor">#F00</span>;</span>&#125;<span class="hljs-class">.generic-error</span> &#123;  <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">20</span>px;</span>  <span class="hljs-attribute">margin</span><span class="hljs-value">: <span class="hljs-number">4</span>px;</span>  <span class="hljs-class">.error</span>(); <span class="hljs-comment">//这里调用默认 border: 2px solid #F00;</span>&#125;<span class="hljs-class">.login-error</span> &#123;  <span class="hljs-attribute">left</span><span class="hljs-value">: <span class="hljs-number">12</span>px;</span>  <span class="hljs-attribute">position</span><span class="hljs-value">: absolute;</span>  <span class="hljs-attribute">top</span><span class="hljs-value">: <span class="hljs-number">20</span>px;</span>  <span class="hljs-class">.error</span>(5px); <span class="hljs-comment">//这里调用 border:5px solid #F00;</span>&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li></ul></pre><p><strong>3.Stylus 的混入语法：</strong></p><pre class="prettyprint" name="code"><code class="hljs scss has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-function">error(borderWidth= <span class="hljs-number">2</span>px)</span> &#123;  <span class="hljs-attribute">border</span><span class="hljs-value">: borderWidth solid <span class="hljs-hexcolor">#F00</span>;</span>  <span class="hljs-attribute">color</span><span class="hljs-value">: <span class="hljs-hexcolor">#F00</span>;</span>&#125;<span class="hljs-class">.generic-error</span> &#123;  <span class="hljs-attribute">padding</span><span class="hljs-value">: <span class="hljs-number">20</span>px;</span>  <span class="hljs-attribute">margin</span><span class="hljs-value">: <span class="hljs-number">4</span>px;</span>  <span class="hljs-function">error()</span>; &#125;<span class="hljs-class">.login-error</span> &#123;  <span class="hljs-attribute">left</span><span class="hljs-value">: <span class="hljs-number">12</span>px;</span>  <span class="hljs-attribute">position</span><span class="hljs-value">: absolute;</span>  <span class="hljs-attribute">top</span><span class="hljs-value">: <span class="hljs-number">20</span>px;</span>  <span class="hljs-function">error(<span class="hljs-number">5</span>px)</span>; &#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li></ul></pre><p>他们最终呈现的效果都如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-class">.generic-error</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">padding</span>:<span class="hljs-value"> <span class="hljs-number">20</span>px</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">4</span>px</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"> <span class="hljs-number">2</span>px solid <span class="hljs-hexcolor">#f00</span></span></span>;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#f00</span></span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.login-error</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">left</span>:<span class="hljs-value"> <span class="hljs-number">12</span>px</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">position</span>:<span class="hljs-value"> absolute</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">top</span>:<span class="hljs-value"> <span class="hljs-number">20</span>px</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"> <span class="hljs-number">5</span>px solid <span class="hljs-hexcolor">#f00</span></span></span>;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#f00</span></span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><h2 id="103d文本"><a name="t9"></a>10.3D文本</h2><p>要生成具有 3D 效果的文本可以使用 text-shadows ，唯一的问题就是当要修改颜色的时候就非常的麻烦，而通过 mixin 和颜色函数可以很轻松的实现：</p><p><strong>1.sass：</strong></p><pre class="prettyprint" name="code"><code class="hljs mel has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-variable">@mixin</span> text3d(<span class="hljs-variable">$color</span>) &#123;  <span class="hljs-keyword">color</span>: <span class="hljs-variable">$color</span>;  <span class="hljs-keyword">text</span>-shadow: <span class="hljs-number">1</span>px <span class="hljs-number">1</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-variable">$color</span>, <span class="hljs-number">5</span><span class="hljs-variable">%)</span>,               <span class="hljs-number">2</span>px <span class="hljs-number">2</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-variable">$color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>,               <span class="hljs-number">3</span>px <span class="hljs-number">3</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-variable">$color</span>, <span class="hljs-number">15</span><span class="hljs-variable">%)</span>,               <span class="hljs-number">4</span>px <span class="hljs-number">4</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-variable">$color</span>, <span class="hljs-number">20</span><span class="hljs-variable">%)</span>,               <span class="hljs-number">4</span>px <span class="hljs-number">4</span>px <span class="hljs-number">2</span>px #<span class="hljs-number">000</span>;&#125;h1 &#123;  font-<span class="hljs-keyword">size</span>: <span class="hljs-number">32</span>pt;  @ include text3d(#<span class="hljs-number">0982</span>c1);&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><p><strong>2.Less CSS：</strong></p><pre class="prettyprint" name="code"><code class="hljs mel has-numbering" onclick="mdcp.signin(event)" style="position: unset;">.text3d(<span class="hljs-variable">@color</span>) &#123;  <span class="hljs-keyword">color</span>: <span class="hljs-variable">@color</span>;  <span class="hljs-keyword">text</span>-shadow: <span class="hljs-number">1</span>px <span class="hljs-number">1</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-variable">@color</span>, <span class="hljs-number">5</span><span class="hljs-variable">%)</span>,               <span class="hljs-number">2</span>px <span class="hljs-number">2</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-variable">@color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>,               <span class="hljs-number">3</span>px <span class="hljs-number">3</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-variable">@color</span>, <span class="hljs-number">15</span><span class="hljs-variable">%)</span>,               <span class="hljs-number">4</span>px <span class="hljs-number">4</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-variable">@color</span>, <span class="hljs-number">20</span><span class="hljs-variable">%)</span>,               <span class="hljs-number">4</span>px <span class="hljs-number">4</span>px <span class="hljs-number">2</span>px #<span class="hljs-number">000</span>;&#125;span &#123;  font-<span class="hljs-keyword">size</span>: <span class="hljs-number">32</span>pt;  .text3d(#<span class="hljs-number">0982</span>c1);&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><p><strong>3.Stylus：</strong></p><pre class="prettyprint" name="code"><code class="hljs mel has-numbering" onclick="mdcp.signin(event)" style="position: unset;">text3d(<span class="hljs-keyword">color</span>)  <span class="hljs-keyword">color</span>: <span class="hljs-keyword">color</span>  <span class="hljs-keyword">text</span>-shadow: <span class="hljs-number">1</span>px <span class="hljs-number">1</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-keyword">color</span>, <span class="hljs-number">5</span><span class="hljs-variable">%)</span>,                <span class="hljs-number">2</span>px <span class="hljs-number">2</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-keyword">color</span>, <span class="hljs-number">10</span><span class="hljs-variable">%)</span>,                <span class="hljs-number">3</span>px <span class="hljs-number">3</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-keyword">color</span>, <span class="hljs-number">15</span><span class="hljs-variable">%)</span>,                <span class="hljs-number">4</span>px <span class="hljs-number">4</span>px <span class="hljs-number">0</span>px darken(<span class="hljs-keyword">color</span>, <span class="hljs-number">20</span><span class="hljs-variable">%)</span>,                <span class="hljs-number">4</span>px <span class="hljs-number">4</span>px <span class="hljs-number">2</span>px #<span class="hljs-number">000</span>span  font-<span class="hljs-keyword">size</span>: <span class="hljs-number">32</span>pt  text3d(#<span class="hljs-number">0982</span>c1)<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li></ul></pre><p>其生成的css最终的效果如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-tag">span</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">font-size</span>:<span class="hljs-value"> <span class="hljs-number">32</span>pt</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#0982c1</span></span></span>;  <span class="hljs-rule"><span class="hljs-attribute">text-shadow</span>:<span class="hljs-value"> <span class="hljs-number">1</span>px <span class="hljs-number">1</span>px <span class="hljs-number">0</span>px <span class="hljs-hexcolor">#097bb7</span>,               <span class="hljs-number">2</span>px <span class="hljs-number">2</span>px <span class="hljs-number">0</span>px <span class="hljs-hexcolor">#0875ae</span>,               <span class="hljs-number">3</span>px <span class="hljs-number">3</span>px <span class="hljs-number">0</span>px <span class="hljs-hexcolor">#086fa4</span>,               <span class="hljs-number">4</span>px <span class="hljs-number">4</span>px <span class="hljs-number">0</span>px <span class="hljs-hexcolor">#07689a</span>,               <span class="hljs-number">4</span>px <span class="hljs-number">4</span>px <span class="hljs-number">2</span>px <span class="hljs-hexcolor">#000</span></span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre><h2 id="11列-columns"><a name="t10"></a>11.列 (Columns)</h2><p>使用数值操作和变量可以很方便的实现适应屏幕大小的布局处理。 <br><strong>1.Sass：</strong></p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;">$<span class="hljs-tag">siteWidth</span>: 1024<span class="hljs-tag">px</span>;$<span class="hljs-tag">gutterWidth</span>: 20<span class="hljs-tag">px</span>;$<span class="hljs-tag">sidebarWidth</span>: 300<span class="hljs-tag">px</span>;<span class="hljs-tag">body</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">0</span> auto</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> $siteWidth</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.content</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">float</span>:<span class="hljs-value"> left</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> $siteWidth - ($sidebarWidth+$gutterWidth)</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.sidebar</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">float</span>:<span class="hljs-value"> left</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">margin-left</span>:<span class="hljs-value"> $gutterWidth</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> $sidebarWidth</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li></ul></pre><p>2.Less CSS：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-at_rule">@<span class="hljs-keyword">siteWidth:</span> <span class="hljs-number">1024</span>px</span>;<span class="hljs-at_rule">@<span class="hljs-keyword">gutterWidth:</span> <span class="hljs-number">20</span>px</span>;<span class="hljs-at_rule">@<span class="hljs-keyword">sidebarWidth:</span> <span class="hljs-number">300</span>px</span>;<span class="hljs-tag">body</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">0</span> auto</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> @siteWidth</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.content</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">float</span>:<span class="hljs-value"> left</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> @siteWidth - (@sidebarWidth+@gutterWidth)</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.sidebar</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">float</span>:<span class="hljs-value"> left</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">margin-left</span>:<span class="hljs-value"> @gutterWidth</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> @sidebarWidth</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li></ul></pre><p><strong>3.Stylus：</strong></p><pre class="prettyprint" name="code"><code class="hljs d has-numbering" onclick="mdcp.signin(event)" style="position: unset;">siteWidth = <span class="hljs-number">1024</span>px;gutterWidth = <span class="hljs-number">20</span>px;sidebarWidth = <span class="hljs-number">300</span>px;<span class="hljs-keyword">body</span> &#123;  margin: <span class="hljs-number">0</span> <span class="hljs-keyword">auto</span>;  width: siteWidth;&#125;.content &#123;  <span class="hljs-built_in">float</span>: left;  width: siteWidth - (sidebarWidth+gutterWidth);&#125;.sidebar &#123;  <span class="hljs-built_in">float</span>: left;  margin-left: gutterWidth;  width: sidebarWidth;&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li></ul></pre><p>其最终生成的css效果如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-tag">body</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">0</span> auto</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> <span class="hljs-number">1024</span>px</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.content</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">float</span>:<span class="hljs-value"> left</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> <span class="hljs-number">704</span>px</span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-class">.sidebar</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">float</span>:<span class="hljs-value"> left</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">margin-left</span>:<span class="hljs-value"> <span class="hljs-number">20</span>px</span></span>;  <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> <span class="hljs-number">300</span>px</span></span>;<span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><h2 id="12高级语法"><a name="t11"></a>12.高级语法</h2><p>1.在sass中，还支持条件语句：</p><pre class="prettyprint"><code class="has-numbering" onclick="mdcp.signin(event)" style="position: unset;">    @if可一个条件单独使用，也可以和@else结合多条件使用<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p>代码如下：</p><pre class="prettyprint" name="code"><code class="hljs scss has-numbering" onclick="mdcp.signin(event)" style="position: unset;">$lte7<span class="hljs-value">: true;</span>$type<span class="hljs-value">: monster;</span><span class="hljs-class">.ib</span>&#123;    <span class="hljs-attribute">display</span><span class="hljs-value">:inline-block;</span>    <span class="hljs-at_rule">@<span class="hljs-keyword">if</span> $lte7 &#123;</span>        *<span class="hljs-attribute">display</span><span class="hljs-value">:inline;</span>        *zoom<span class="hljs-value">:<span class="hljs-number">1</span>;</span>    &#125;&#125;<span class="hljs-tag">p</span> &#123;  <span class="hljs-at_rule">@<span class="hljs-keyword">if</span> $type ==<span class="hljs-preprocessor"> ocean</span> &#123;</span>    <span class="hljs-attribute">color</span><span class="hljs-value">: blue;</span>  &#125; <span class="hljs-at_rule">@<span class="hljs-keyword">else</span><span class="hljs-preprocessor"> if</span> $type ==<span class="hljs-preprocessor"> matador</span> &#123;</span>    <span class="hljs-attribute">color</span><span class="hljs-value">: red;</span>  &#125; <span class="hljs-at_rule">@<span class="hljs-keyword">else</span><span class="hljs-preprocessor"> if</span> $type ==<span class="hljs-preprocessor"> monster</span> &#123;</span>    <span class="hljs-attribute">color</span><span class="hljs-value">: green;</span>  &#125; <span class="hljs-at_rule">@<span class="hljs-keyword">else</span> &#123;</span>    <span class="hljs-attribute">color</span><span class="hljs-value">: black;</span>  &#125;&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li></ul></pre><p>其最终的css代码如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-class">.ib</span><span class="hljs-rules">&#123;    <span class="hljs-rule"><span class="hljs-attribute">display</span>:<span class="hljs-value">inline-block</span></span>;    <span class="hljs-rule">*<span class="hljs-attribute">display</span>:<span class="hljs-value">inline</span></span>;    <span class="hljs-rule">*<span class="hljs-attribute">zoom</span>:<span class="hljs-value"><span class="hljs-number">1</span></span></span>;<span class="hljs-rule">&#125;</span></span><span class="hljs-tag">p</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">color</span>:<span class="hljs-value"> green</span></span>; <span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre><p>2.除却条件语句，sass还支持for循环：</p><p>for循环有两种形式，分别为：</p><pre class="prettyprint" name="code"><code class="hljs livecodeserver has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-number">1.</span>@<span class="hljs-keyword">for</span> $var <span class="hljs-built_in">from</span> &lt;start&gt; through &lt;<span class="hljs-function"><span class="hljs-keyword">end</span>&gt;</span><span class="hljs-number">2.</span>@<span class="hljs-keyword">for</span> $var <span class="hljs-built_in">from</span> &lt;start&gt; <span class="hljs-built_in">to</span> &lt;<span class="hljs-function"><span class="hljs-keyword">end</span>&gt;。</span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><p>其中$i表示变量，start表示起始值，end表示结束值，这两个的区别是关键字through表示包括end这个数，而to则不包括end这个数。</p><pre class="prettyprint" name="code"><code class="hljs haml has-numbering" onclick="mdcp.signin(event)" style="position: unset;">@for $i from 1 to 10 &#123;  .border-#&#123;<span class="ruby"><span class="hljs-variable">$i</span>&#125;</span> &#123;    border: #&#123;<span class="ruby"><span class="hljs-variable">$i</span>&#125;</span>px solid blue;  &#125;&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p>同时也支持while循环：</p><pre class="prettyprint" name="code"><code class="hljs mel has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-variable">$i</span>: <span class="hljs-number">6</span>;<span class="hljs-variable">@while</span> <span class="hljs-variable">$i</span> &gt; <span class="hljs-number">0</span> &#123;  .item-#&#123;<span class="hljs-variable">$i</span>&#125; &#123; width: <span class="hljs-number">2</span>em * <span class="hljs-variable">$i</span>; &#125;  <span class="hljs-variable">$i</span>: <span class="hljs-variable">$i</span> - <span class="hljs-number">2</span>;&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><p>最后，同时支持each命令，作用与for类似：</p><pre class="prettyprint" name="code"><code class="hljs ruby has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-variable">$animal</span>-<span class="hljs-symbol">list:</span> puma, sea-slug, egret, salamander;<span class="hljs-variable">@each</span> <span class="hljs-variable">$animal</span> <span class="hljs-keyword">in</span> <span class="hljs-variable">$animal</span>-list &#123;  .<span class="hljs-comment">#&#123;$animal&#125;-icon &#123;</span>    background-<span class="hljs-symbol">image:</span> url(<span class="hljs-string">'/img/<span class="hljs-subst">#&#123;<span class="hljs-variable">$animal</span>&#125;</span>.png'</span>);  &#125;&#125;<div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><p>其css最终效果如下：</p><pre class="prettyprint" name="code"><code class="hljs css has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="hljs-class">.puma-icon</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background-image</span>:<span class="hljs-value"> <span class="hljs-function">url(<span class="hljs-string">'/img/puma.png'</span>)</span></span></span>; <span class="hljs-rule">&#125;</span></span><span class="hljs-class">.sea-slug-icon</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background-image</span>:<span class="hljs-value"> <span class="hljs-function">url(<span class="hljs-string">'/img/sea-slug.png'</span>)</span></span></span>; <span class="hljs-rule">&#125;</span></span><span class="hljs-class">.egret-icon</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background-image</span>:<span class="hljs-value"> <span class="hljs-function">url(<span class="hljs-string">'/img/egret.png'</span>)</span></span></span>; <span class="hljs-rule">&#125;</span></span><span class="hljs-class">.salamander-icon</span> <span class="hljs-rules">&#123;  <span class="hljs-rule"><span class="hljs-attribute">background-image</span>:<span class="hljs-value"> <span class="hljs-function">url(<span class="hljs-string">'/img/salamander.png'</span>)</span></span></span>; <span class="hljs-rule">&#125;</span></span><div class="hljs-button signin" data-title="登录后复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><p>以上就是sass，Less css与stylus的最显著的区别。</p>                                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> summer </tag>
            
            <tag> web </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python爬取梨视频</title>
      <link href="python/spider/pear-spider/"/>
      <url>python/spider/pear-spider/</url>
      
        <content type="html"><![CDATA[<h2 id="python爬虫程序-下载梨视频到本地"><a href="#python爬虫程序-下载梨视频到本地" class="headerlink" title="python爬虫程序,下载梨视频到本地"></a>python爬虫程序,下载梨视频到本地</h2><h2 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h2><p>关于python的介绍可以参考:python简介</p><p>python安装参考:Python安装以及版本检测</p><p>pycharm安装可以参考:PyCharm的安装和破解</p><p>pip安装参考:添加链接描述</p><p>request安装:<code>pip install request</code></p><p>urllib安装:<code>pip install urllib</code></p><h2 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h2><p>梨视频首页</p><h2 id="具体实现"><a href="#具体实现" class="headerlink" title="具体实现"></a>具体实现</h2><p>通过两次请求</p><h2 id="源代码"><a href="#源代码" class="headerlink" title="源代码"></a>源代码</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by xiaoming</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;&gt;</span></span><br><span class="line"><span class="keyword">from</span> urllib.request <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> requests <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> re <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> os <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> random <span class="keyword">import</span> *</span><br><span class="line"><span class="comment"># makedirs(&#x27;视频&#x27;)</span></span><br><span class="line">titlep = []</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">single_page</span>(<span class="params">url,name,video_num</span>):</span></span><br><span class="line">    <span class="keyword">if</span> path.exists(name):</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        makedirs(name)</span><br><span class="line"></span><br><span class="line">    response = get(url)</span><br><span class="line"></span><br><span class="line">    response = response.text</span><br><span class="line"></span><br><span class="line">    rep = findall(<span class="string">&#x27;categoryem.*?href=\&quot;video(.*?)\&quot;&#x27;</span>,response,S)</span><br><span class="line">    <span class="comment"># print(rep)</span></span><br><span class="line">    j = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> rep:</span><br><span class="line">        j += <span class="number">1</span></span><br><span class="line">        i = <span class="string">&#x27;https://www.pearvideo.com/video&#x27;</span> + i</span><br><span class="line">        ori_video_url = one_video(i)</span><br><span class="line">        print(<span class="string">&#x27;正在下载第&#x27;</span>,j,<span class="string">&#x27;个视频...&#x27;</span>)</span><br><span class="line">        suiji = random()</span><br><span class="line">        full_name = name+<span class="string">&#x27;/&#x27;</span> + titlep[<span class="number">0</span>] + <span class="string">&#x27;.mp4&#x27;</span></span><br><span class="line">        <span class="comment"># full_name = name+&#x27;/&#x27; + str(suiji)[2:] + &#x27;.mp4&#x27;</span></span><br><span class="line">        urlretrieve(ori_video_url, full_name)</span><br><span class="line">        print(<span class="string">&#x27;成功保存视频: &#x27;</span>,full_name)</span><br><span class="line">        <span class="keyword">if</span> j == video_num:</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">当你的才华还撑不起你的野心时,那你就应该静下心来学习</span></span><br><span class="line"><span class="string">当你的能力还驾驭不了你的目标时,那就应该沉下心来历练</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">one_video</span>(<span class="params">url</span>):</span></span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    梨视频网站,传递一个单个视频页面,返回一个视频的原始地址</span></span><br><span class="line"><span class="string">    :param url:</span></span><br><span class="line"><span class="string">    :return:</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    response = get(url)</span><br><span class="line"></span><br><span class="line">    response = response.text</span><br><span class="line"></span><br><span class="line">    <span class="comment"># print(response)</span></span><br><span class="line"></span><br><span class="line">    rep = findall(<span class="string">r&#x27;https://video.pearvideo.com/mp4/(.*?)mp4&#x27;</span>, response, S)</span><br><span class="line"></span><br><span class="line">    titlee = findall(<span class="string">r&#x27;class=&quot;video-tt&quot;.*?&gt;(.*?)&lt;/h1&gt;&#x27;</span>, response, S)</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> titlee:</span><br><span class="line">        titlep.clear()</span><br><span class="line">        titlep.append(i)</span><br><span class="line">    print(titlep)</span><br><span class="line">    <span class="comment"># print(rep)</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> rep:</span><br><span class="line">        i = <span class="string">&#x27;https://video.pearvideo.com/mp4/&#x27;</span> + i + <span class="string">&#x27;mp4&#x27;</span></span><br><span class="line">        print(i)</span><br><span class="line">        <span class="keyword">return</span> i</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>():</span></span><br><span class="line">    mulu = &#123;</span><br><span class="line">        <span class="string">&#x27;新知&#x27;</span>:<span class="string">&#x27;10&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;社会&#x27;</span>:<span class="string">&#x27;1&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;世界&#x27;</span>:<span class="string">&#x27;2&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;体育&#x27;</span>:<span class="string">&#x27;9&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;生活&#x27;</span>:<span class="string">&#x27;5&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;科技&#x27;</span>:<span class="string">&#x27;8&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;娱乐&#x27;</span>:<span class="string">&#x27;4&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;财富&#x27;</span>:<span class="string">&#x27;3&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;汽车&#x27;</span>:<span class="string">&#x27;31&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;美食&#x27;</span>:<span class="string">&#x27;6&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;音乐&#x27;</span>:<span class="string">&#x27;59&#x27;</span>,</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment"># 新知 社会 世界 体育 生活 科技 娱乐 财富 汽车 美食 音乐 拍客</span></span><br><span class="line">    url = <span class="string">&#x27;https://www.pearvideo.com/category_&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> mulu:</span><br><span class="line">        print(i,end=<span class="string">&quot; &quot;</span>)</span><br><span class="line">    print()</span><br><span class="line">    choice = <span class="built_in">input</span>(<span class="string">&quot;请选择需要的视频类型:&quot;</span>)</span><br><span class="line">    num = mulu[choice]</span><br><span class="line">    url = url + num</span><br><span class="line"></span><br><span class="line">    video_num = <span class="built_in">int</span>(<span class="built_in">input</span>(<span class="string">&quot;请输入要下载视频的数量:&quot;</span>))</span><br><span class="line">    single_page(url,choice,video_num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">main()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> regex </tag>
            
            <tag> spider </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python爬取妹子图</title>
      <link href="python/GUI/tkinter/mzitu-spider/"/>
      <url>python/GUI/tkinter/mzitu-spider/</url>
      
        <content type="html"><![CDATA[<h3 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h3><ol><li>python的安装</li></ol><p>利用python爬虫爬取图片，首先要进行安装python</p><p>可以参考:<a href="https://victorfengming.gitee.io/blog/python-install-window/">window下python的安装与版本检测</a><br>2. IDE的安装</p><p>PyCharm 是一种 Python IDE，带有一整套可以帮助用户在使用 Python 语言开发时提高其效率的工具，比如调试、语法高亮、Project 管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外，该 IDE 提供了一些高级功能，以用于支持 Django 框架下的专业 Web 开发。其中免费的<a href="https://www.jetbrains.com/pycharm/download/download-thanks.html?platform=windows&code=PCC&utm_source=so&utm_source=so">社区版（点击即下载）</a>已经能够满足我们的需求，它的安装可以参考:<a href="https://victorfengming.gitee.io/blog/pycharm-install/">PyCharm的安装以及破解</a>,关于它的使用可以参考<a href="https://www.luffycity.com/free/39">Pycharm使用秘籍</a><br>3. requests的安装<br>这里我们在终端中用pip安装<br><code>pip install requests</code></p><p>如果出现pip没有找到或者不是系统命令,可以参考<a href="https://blog.csdn.net/qq_40223983/article/details/96832040">python如何安装pip</a></p><h3 id="爬虫简介"><a href="#爬虫简介" class="headerlink" title="爬虫简介"></a>爬虫简介</h3><p>爬虫是什么？</p><p>爬虫爬取的过程从本质上说就是在模拟 HTTP 请求，记住这句话，这就是我们后面经常需要做的事情。一般用户获取网络数据的方式有两种：</p><ul><li>a. 浏览器提交 HTTP 请求—&gt;下载网页代码—&gt;解析成页面。</li><li>b. 模拟浏览器发送请求（获取网页代码）-&gt;提取有用的数据-&gt;存放于数据库或文件中。</li></ul><p>爬虫就是在做第二种事情，大致过程如下:</p><p>i. 通过 HTTP 库向目标站点发起请求，即发送一个 Request，请求可以包含额外的 headers 等信息，等待服务器的响应</p><p>ii. 如果服务器正常响应，会得到一个 Response，Response 的内容便是所要获取的页面内容，类型可能有 HTML、JSON、二进制文件（如图片、视频等类型）。</p><p>iii. 得到的内容可能是 HTML，可以用正则表达式、网页解析库进行解析。可能是 JSON，可以直接转成 JOSN 对象进行解析，可能是二进制数据，可以保存或者进一步处理</p><p>iv. 保存形式多样，可以保存成文本，也可以保存至数据库，或者保存成特定格式的文件。<br>许多读者可能不知道上面具体在做什么，那么接下来我们通过浏览器抓包分析上面的过程，笔者推荐使用 Chrome，对开发者很友好，后续我们会经常使用到，Chrome 下载，如果下载速度较慢，建议使用国内 Chrome 镜像下载安装。</p><h3 id="利用python抓取网络图片的步骤："><a href="#利用python抓取网络图片的步骤：" class="headerlink" title="利用python抓取网络图片的步骤："></a>利用python抓取网络图片的步骤：</h3><ol><li><p>根据给定的网址获取网页源代码</p></li><li><p>利用正则表达式把源代码中的图片地址过滤出来</p></li><li><p>根据过滤出来的图片地址下载网络图片</p></li></ol><h3 id="爬虫部分-源码"><a href="#爬虫部分-源码" class="headerlink" title="爬虫部分(源码)"></a>爬虫部分(源码)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by victor</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> urllib <span class="keyword">import</span> request</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">妹子图网站反扒手段 ,限制方位来源,需在headers中加入 Referer 跳转来源</span></span><br><span class="line"><span class="string">urlretrieve 无法加入请求头headers</span></span><br><span class="line"><span class="string">我们使用bytes直接下载图片</span></span><br><span class="line"><span class="string">同时需注意限制访问时间间隔,访问频次过快,服务器进制访问</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">#### 注意图片下载地址是.jpg格式,我们下午使用链接不正确所以可以下载但无法打开</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">ori_video</span>(<span class="params">meizi_url</span>):</span></span><br><span class="line">    headers = &#123;</span><br><span class="line">        <span class="string">&#x27;Referer&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;user-agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment"># print(meizi_url)</span></span><br><span class="line">    meizi_html = requests.get(meizi_url,headers = headers).text</span><br><span class="line">    end_url = re.findall(<span class="string">&quot;&lt;span&gt;(\d+?)&lt;/span&gt;&lt;/a&gt;&lt;a href=&#x27;https://www.mzitu.com/\d*?/2&#x27;&gt;&lt;span&gt;下一页&amp;raquo&quot;</span>,meizi_html)</span><br><span class="line">    name_id = re.search(<span class="string">&#x27;&lt;h2 class=&quot;main-title&quot;&gt;(.*?)&lt;/h2&gt;&#x27;</span>,meizi_html).group(<span class="number">1</span>)</span><br><span class="line">    name = re.sub(<span class="string">&#x27;!&#x27;</span>,<span class="string">&#x27;&#x27;</span>,name_id)</span><br><span class="line">    print(end_url)</span><br><span class="line">    end_url = <span class="built_in">int</span>(end_url[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> x <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>,end_url):</span><br><span class="line">        newurl = meizi_url + <span class="string">&#x27;/&#x27;</span> + <span class="built_in">str</span>(x)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># print(name)</span></span><br><span class="line">        newurl = meizi_url + <span class="string">&#x27;/&#x27;</span> +  <span class="built_in">str</span>(x)</span><br><span class="line">        <span class="comment"># print(newurl)</span></span><br><span class="line">        html = requests.get(newurl,headers = headers).text</span><br><span class="line">        end_re = re.findall(<span class="string">r&#x27;&lt;div class=&quot;main-image&quot;&gt;&lt;p&gt;&lt;a href=&quot;.+?&quot; &gt;&lt;img src=&quot;(.*?)&quot;&#x27;</span>,html)</span><br><span class="line">        print(end_re[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line">        headers = &#123;</span><br><span class="line">            <span class="string">&#x27;Referer&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;user-agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment"># urlretrieve(end_re[0],path+&#x27;/&#x27;+ str(x)) 不能加请求头</span></span><br><span class="line">        req = request.Request(end_re[<span class="number">0</span>],headers = headers)</span><br><span class="line">        response = request.urlopen(req)</span><br><span class="line">        fname = end_re[<span class="number">0</span>].split(<span class="string">&#x27;/&#x27;</span>)[-<span class="number">1</span>]</span><br><span class="line">        print(<span class="string">&#x27;正在下载: &#x27;</span>,fname)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> name <span class="keyword">not</span> <span class="keyword">in</span> os.listdir():</span><br><span class="line">            os.mkdir(name)</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(name + <span class="string">&#x27;/&#x27;</span> + fname, <span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            f.write(response.read())</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27; 反反爬  设置时间间隔 防止服务器封锁IP或禁止访问&#x27;&#x27;&#x27;</span></span><br><span class="line">        time.sleep(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载一页的内容</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">page_one</span>():</span></span><br><span class="line">    url = <span class="string">&#x27;https://www.mzitu.com/&#x27;</span></span><br><span class="line">    headers = &#123;</span><br><span class="line">        <span class="string">&#x27;Referer&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;user-agent&#x27;</span>:<span class="string">&#x27;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    html = requests.get(url,headers = headers).text</span><br><span class="line">    <span class="comment"># print(html)</span></span><br><span class="line">    ret = re.findall(<span class="string">&#x27;&lt;li&gt;&lt;a href=&quot;(.*?)&quot; target=&quot;_blank&quot;&gt;&lt;img class=&#x27;</span>,html)</span><br><span class="line">    print(ret)</span><br><span class="line">    <span class="comment"># for meizi_url in ret:</span></span><br><span class="line">    meizi_url = <span class="string">&#x27;https://www.mzitu.com/166998&#x27;</span></span><br><span class="line">    ori_video(meizi_url)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 调用</span></span><br><span class="line">page_one()</span><br></pre></td></tr></table></figure><h3 id="带有图形界面部分-源码"><a href="#带有图形界面部分-源码" class="headerlink" title="带有图形界面部分(源码)"></a>带有图形界面部分(源码)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by victor</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;带有图形界面的妹子图爬虫程序&gt;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">加入了顶部颜色的更改,实现了排它思想</span></span><br><span class="line"><span class="string">下载按钮在下载中的按钮颜色更改</span></span><br><span class="line"><span class="string">加上了 一个顶部的转台信息栏</span></span><br><span class="line"><span class="string">加入了多线程功能,解决了在下载过程中图形界面卡顿问题</span></span><br><span class="line"><span class="string">TODO 显示预览图</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 导包</span></span><br><span class="line"><span class="keyword">from</span> tkinter <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> tkinter <span class="keyword">import</span> ttk</span><br><span class="line"><span class="keyword">from</span> tkinter.filedialog <span class="keyword">import</span> askdirectory</span><br><span class="line"><span class="keyword">from</span> requests <span class="keyword">import</span> get</span><br><span class="line"><span class="keyword">from</span> re <span class="keyword">import</span> findall</span><br><span class="line"><span class="keyword">from</span> re <span class="keyword">import</span> search</span><br><span class="line"><span class="keyword">from</span> re <span class="keyword">import</span> sub</span><br><span class="line"><span class="keyword">from</span> os <span class="keyword">import</span> listdir</span><br><span class="line"><span class="keyword">from</span> os <span class="keyword">import</span> mkdir</span><br><span class="line"><span class="keyword">from</span> os <span class="keyword">import</span> path</span><br><span class="line"><span class="keyword">from</span> urllib.request <span class="keyword">import</span> Request</span><br><span class="line"><span class="keyword">from</span> urllib.request <span class="keyword">import</span> urlopen</span><br><span class="line"><span class="keyword">from</span> time <span class="keyword">import</span> sleep</span><br><span class="line"><span class="keyword">from</span> threading <span class="keyword">import</span> Thread</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Tk_gui</span>():</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        初始化魔术方法</span></span><br><span class="line"><span class="string">        用于设置界面的初始状态</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 创建tkinter窗口</span></span><br><span class="line">        self.root = Tk()</span><br><span class="line">        <span class="comment"># 设置窗口的标题</span></span><br><span class="line">        self.root.title(<span class="string">&#x27;一起来看美女&#x27;</span>)</span><br><span class="line">        <span class="comment"># 设置窗口的长和宽,最大值和最小值设置相同,用户不可调整窗口大小</span></span><br><span class="line">        self.root.minsize(<span class="number">780</span>, <span class="number">370</span>)</span><br><span class="line">        self.root.maxsize(<span class="number">780</span>, <span class="number">570</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 初始化</span></span><br><span class="line">        self.curr_page = <span class="number">1</span></span><br><span class="line">        self.page_max = self.get_page_max()</span><br><span class="line">        <span class="comment"># 初始化主要url</span></span><br><span class="line">        self.curr_url = <span class="string">&#x27;https://www.mzitu.com/&#x27;</span></span><br><span class="line">        self.tit_list = s.page_one(self.curr_url)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 调用主要逻辑执行函数</span></span><br><span class="line">        self.main_logic()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">thread_it</span>(<span class="params">self, func, *args</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        将函数打包进线程</span></span><br><span class="line"><span class="string">        :param func:</span></span><br><span class="line"><span class="string">        :param args:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 创建</span></span><br><span class="line">        t = Thread(target=func, args=args)</span><br><span class="line">        <span class="comment"># 守护 !!!</span></span><br><span class="line">        t.setDaemon(<span class="literal">True</span>)</span><br><span class="line">        <span class="comment"># 启动</span></span><br><span class="line">        t.start()</span><br><span class="line">        <span class="comment"># 阻塞--卡死界面！</span></span><br><span class="line">        <span class="comment"># t.join()</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_save_path</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        path_ = askdirectory()</span><br><span class="line">        Tk_gui.path.<span class="built_in">set</span>(path_)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_page_max</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">50</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">main_logic</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        主业务逻辑</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 顶部信息栏</span></span><br><span class="line">        topp = Frame()</span><br><span class="line">        topp.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 内容栏</span></span><br><span class="line">        self.cont = Frame()</span><br><span class="line">        self.cont.grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 输入选项操作</span></span><br><span class="line">        self.indo = Frame()</span><br><span class="line">        self.indo.grid(row=<span class="number">0</span>, column=<span class="number">1</span>, rowspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 状态栏</span></span><br><span class="line">        self.stat = Frame()</span><br><span class="line">        self.stat.grid(row=<span class="number">2</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        self.top_menu(topp)</span><br><span class="line">        self.stat_info()</span><br><span class="line">        self.main_content(self.get_num_list())</span><br><span class="line"></span><br><span class="line">        self.get_title_list(<span class="string">&#x27;https://www.mzitu.com&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 加入主消息循环</span></span><br><span class="line">        self.root.mainloop()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">download</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        正式下载图片</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        self.btn5[<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;pink&#x27;</span></span><br><span class="line">        para = self.search()</span><br><span class="line">        s.ori_video(para[<span class="number">0</span>], para[<span class="number">1</span>], para[<span class="number">2</span>])</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">search</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        搜索预加载页面中的图片个数</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># print(&quot;下载url:&quot;)</span></span><br><span class="line">        index = <span class="built_in">int</span>(self.number_chosen.get()) - <span class="number">1</span></span><br><span class="line">        <span class="comment"># print(&#x27;index:%d&#x27;%index)</span></span><br><span class="line">        url = tit_list[<span class="number">0</span>][index]</span><br><span class="line">        para = s.pre_download(url)</span><br><span class="line">        self.detail_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&quot;本页有&quot;</span> + <span class="built_in">str</span>(para[<span class="number">0</span>]) + <span class="string">&quot;张图&quot;</span></span><br><span class="line">        <span class="keyword">return</span> para</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_title_list</span>(<span class="params">self, url</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        获取标题列表内容</span></span><br><span class="line"><span class="string">        :param url:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="keyword">global</span> tit_list</span><br><span class="line">        tit_list = s.page_one(url)</span><br><span class="line">        self.info[<span class="string">&quot;text&quot;</span>] = <span class="string">&quot;\n&quot;</span>.join(tit_list[<span class="number">1</span>])</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_num_list</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        获取数值列表</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        num = []</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">25</span>):</span><br><span class="line">            num.append(<span class="built_in">str</span>(i))</span><br><span class="line">        num_str = <span class="string">&quot;\n&quot;</span>.join(num)</span><br><span class="line">        <span class="keyword">return</span> num_str</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">set_top_bg</span>(<span class="params">self,<span class="built_in">id</span></span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :param id: id 是按钮摆放的位置,int类型的</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 还原现场</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> self.button_list:</span><br><span class="line">            i[<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;skyblue&#x27;</span></span><br><span class="line"></span><br><span class="line">        self.button_list[<span class="built_in">id</span>-<span class="number">1</span>][<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;pink&#x27;</span></span><br><span class="line">        <span class="comment"># for i in</span></span><br><span class="line">        <span class="comment">#     if curr == i:</span></span><br><span class="line">        <span class="comment">#         i[&#x27;bg&#x27;]==&#x27;gray&#x27;</span></span><br><span class="line">        <span class="comment">#     else:</span></span><br><span class="line">        <span class="comment">#         i[&#x27;bg&#x27;]==&#x27;&#x27;</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">update_page_url</span>(<span class="params">self, option, reg_url</span>):</span></span><br><span class="line">        <span class="keyword">if</span> option:</span><br><span class="line">            <span class="keyword">if</span> option == <span class="number">2</span>:</span><br><span class="line">                print(<span class="string">&#x27;下一页&#x27;</span>)</span><br><span class="line">                <span class="keyword">if</span> self.curr_page &lt; self.page_max:</span><br><span class="line">                    self.curr_page += <span class="number">1</span></span><br><span class="line">            <span class="keyword">elif</span> option == <span class="number">1</span>:</span><br><span class="line">                print(<span class="string">&#x27;上一页&#x27;</span>)</span><br><span class="line">                <span class="keyword">if</span> self.curr_page &gt; <span class="number">1</span>:</span><br><span class="line">                    self.curr_page -= <span class="number">1</span></span><br><span class="line">            <span class="keyword">elif</span> option == <span class="number">3</span>:</span><br><span class="line">                self.curr_page = <span class="built_in">int</span>(self.page_chosen.get())</span><br><span class="line">        <span class="keyword">if</span> reg_url:</span><br><span class="line">            <span class="comment"># TODO 设置更新按钮的背景颜色</span></span><br><span class="line">            <span class="comment"># 调用set_button_color</span></span><br><span class="line">            <span class="comment"># 重置页面数</span></span><br><span class="line">            self.curr_page = <span class="number">1</span></span><br><span class="line">            self.curr_url = reg_url</span><br><span class="line">        <span class="keyword">if</span> self.curr_page == <span class="number">1</span>:</span><br><span class="line">            url = self.curr_url</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            url = self.curr_url + <span class="string">&#x27;page/&#x27;</span> + <span class="built_in">str</span>(self.curr_page) + <span class="string">&#x27;/&#x27;</span></span><br><span class="line">        print(self.curr_page)</span><br><span class="line">        self.page_info[<span class="string">&#x27;text&#x27;</span>] = <span class="string">&#x27;当前页数:&#x27;</span> + <span class="built_in">str</span>(self.curr_page)</span><br><span class="line">        self.get_title_list(url)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">top_menu</span>(<span class="params">self, topp</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        用于绘制顶部菜单</span></span><br><span class="line"><span class="string">        :param topp:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        self.button_list = []</span><br><span class="line">        <span class="comment"># 菜单栏</span></span><br><span class="line">        url_list = &#123;</span><br><span class="line">            <span class="string">&#x27;推荐&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;性感&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/xinggan/&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;日本&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/japan/&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;台湾&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/taiwan/&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;清纯&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/mm/&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment"># update_page_url函数是用来更新页面的内容以及后面要下载的url的</span></span><br><span class="line">        menu = Button(topp, text=<span class="string">&#x27;&#x27;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">1</span>)</span><br><span class="line">        menu.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">put_button</span>(<span class="params">key, col</span>):</span></span><br><span class="line">            <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">            用于画出按钮组件</span></span><br><span class="line"><span class="string">            :param contain:按钮显示的文本内容</span></span><br><span class="line"><span class="string">            :param key: 命令执行的函数选择的键</span></span><br><span class="line"><span class="string">            :param col: 按钮放置的列数</span></span><br><span class="line"><span class="string">            :return:</span></span><br><span class="line"><span class="string">            &#x27;&#x27;&#x27;</span></span><br><span class="line">            <span class="comment"># self.curr_button = StringVar()</span></span><br><span class="line">            <span class="comment"># TODO 怎么解决一个command 执行两个函数的问题</span></span><br><span class="line">            <span class="comment"># 这里用is机制的占了个位置,让两个函数都执行,随便返回点啥,我都不要,哈哈哈哈哈</span></span><br><span class="line">            <span class="comment"># 之前尝试过用函数的参数传递,但是有点不太好管理</span></span><br><span class="line">            <span class="comment"># 后来用的+号,程序报错,虽然界面中看不出来,但是我还是有点强迫症的让他不报错</span></span><br><span class="line">            self.menu = Button(topp, text=key, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">7</span>,\</span><br><span class="line">            command=<span class="keyword">lambda</span>: self.update_page_url(option=<span class="number">0</span>, reg_url=url_list[key]) <span class="keyword">is</span> \</span><br><span class="line">                            self.set_top_bg(col))</span><br><span class="line"></span><br><span class="line">            self.menu.grid(row=<span class="number">0</span>, column=col)</span><br><span class="line">            self.button_list.append(self.menu)</span><br><span class="line">            <span class="keyword">for</span> i <span class="keyword">in</span> self.button_list:</span><br><span class="line">                i[<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;skyblue&#x27;</span></span><br><span class="line">            self.button_list[<span class="number">0</span>][<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;pink&#x27;</span></span><br><span class="line">            <span class="comment"># if key == self.curr_button:</span></span><br><span class="line">            <span class="comment">#     menu[&#x27;background&#x27;] = &#x27;gray&#x27;</span></span><br><span class="line"></span><br><span class="line">        i = <span class="number">1</span></span><br><span class="line">        <span class="keyword">for</span> contain <span class="keyword">in</span> url_list.keys():</span><br><span class="line">            put_button(contain, i)</span><br><span class="line">            i += <span class="number">1</span></span><br><span class="line">        <span class="comment">#</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 前进和后退,进行页数的更改</span></span><br><span class="line">        <span class="comment"># option为标记位,0为不改变</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 顶部的显示当前页数的lable</span></span><br><span class="line">        <span class="comment"># 定义成类属性,以便于在Spider类中更改其值</span></span><br><span class="line">        self.page_info = Label(topp, text=<span class="string">&#x27;&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                               font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">10</span>)</span><br><span class="line">        self.page_info.grid(row=<span class="number">0</span>, column=<span class="number">6</span>)</span><br><span class="line"></span><br><span class="line">        self.page_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;当前页数:1&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">main_content</span>(<span class="params">self, num_str</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        主要内容界面,包括数字列表的显示,标题列表的显示以及右边输入框和下载按钮部分</span></span><br><span class="line"><span class="string">        :param num_str:数字列表显示内容</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 左边的序号栏</span></span><br><span class="line">        one = Label(self.cont, text=num_str, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>),relief=<span class="string">&#x27;ridge&#x27;</span>)</span><br><span class="line">        one.grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 中间的主要信息栏</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        relief(可选值为：flat(默认),sunken,raised,groove,ridge)，borderwidth(边框的宽度，单位是像素，默认根据系统而定，一般是1或2像素)</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        self.info = Label(self.cont, text=<span class="string">&#x27;info&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                          font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">49</span>,relief=<span class="string">&#x27;ridge&#x27;</span>)</span><br><span class="line">        self.info.grid(row=<span class="number">1</span>, column=<span class="number">1</span>, columnspan=<span class="number">6</span>)</span><br><span class="line">        <span class="comment"># 右边的选择栏</span></span><br><span class="line">        <span class="comment"># 上面的提升lable</span></span><br><span class="line">        ttk.Label(self.indo, text=<span class="string">&quot;\n\n\n选择一个&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>)).grid(column=<span class="number">0</span>, row=<span class="number">4</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        <span class="comment"># 添加一个标签，并将其列设置为1，行设置为0</span></span><br><span class="line">        <span class="comment"># 中间的下拉框</span></span><br><span class="line">        number = StringVar()</span><br><span class="line">        <span class="comment"># 这里直接定义成为类的属性,以便于其他方法中直接获取其选择的页数</span></span><br><span class="line">        self.number_chosen = ttk.Combobox(self.indo, width=<span class="number">12</span>, textvariable=number)</span><br><span class="line">        self.number_chosen[<span class="string">&#x27;values&#x27;</span>] = <span class="built_in">tuple</span>(<span class="built_in">range</span>(<span class="number">1</span>, <span class="number">25</span>))  <span class="comment"># 设置下拉列表的值</span></span><br><span class="line">        self.number_chosen.grid(column=<span class="number">0</span>, row=<span class="number">5</span>, columnspan=<span class="number">2</span>)  <span class="comment"># 设置其在界面中出现的位置 column代表列 row 代表行</span></span><br><span class="line">        self.number_chosen.current(<span class="number">0</span>)  <span class="comment"># 设置下拉列表默认显示的值，0为 numberChosen[&#x27;values&#x27;] 的下标值</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 由于进行了类的封装,所以不需要借用列表的穿透性了</span></span><br><span class="line">        <span class="comment"># 直接定义一个类的成员属性即可传递到类中的任何位置</span></span><br><span class="line">        <span class="comment"># 这里实时更新当前选中的数字内容,以便于按下下载按钮时能够定位到准确的页面</span></span><br><span class="line">        <span class="comment"># TODO 可以优化到其他位置,减少功能模块之间的耦合性</span></span><br><span class="line">        <span class="comment"># self.user_choose_num = self.number_chosen.get()</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 点击查询按钮</span></span><br><span class="line">        btn4 = Button(self.indo, text=<span class="string">&quot;查询图片个数&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>),background = <span class="string">&#x27;gray&#x27;</span>, command=<span class="keyword">lambda</span>: self.thread_it(self.search))</span><br><span class="line">        btn4.grid(column=<span class="number">0</span>, row=<span class="number">6</span>, columnspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 外加的详细信息栏</span></span><br><span class="line">        <span class="comment"># 这里直接定义成为类的属性,以便于其他方法中直接修改其内容</span></span><br><span class="line">        self.detail_info = Label(self.indo, text=<span class="string">&#x27;&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                                 font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">10</span>)</span><br><span class="line">        self.detail_info.grid(row=<span class="number">7</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        <span class="comment"># 点击下载的按钮</span></span><br><span class="line">        self.btn5 = Button(self.indo, text=<span class="string">&quot;下载此页图片&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>),background = <span class="string">&#x27;gray&#x27;</span>, command=<span class="keyword">lambda</span>: self.thread_it(self.download))</span><br><span class="line">        self.btn5.grid(column=<span class="number">0</span>, row=<span class="number">12</span>, columnspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 外加的详细下载信息栏</span></span><br><span class="line">        <span class="comment"># 定义成类属性,以便于在Spider类中更改其值</span></span><br><span class="line">        Tk_gui.terminal_info = Label(self.stat, text=<span class="string">&#x27;&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                                     font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>))</span><br><span class="line">        Tk_gui.terminal_info.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        Tk_gui.terminal_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">        menu = Button(self.indo, text=<span class="string">&quot; 上一页&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>,</span><br><span class="line">                      command=<span class="keyword">lambda</span>: self.thread_it(<span class="keyword">lambda</span>: self.update_page_url(option=<span class="number">1</span>, reg_url=<span class="string">&#x27;&#x27;</span>)))</span><br><span class="line">        menu.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        menu = Button(self.indo, text=<span class="string">&quot;下一页 &quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>,</span><br><span class="line">                      command=<span class="keyword">lambda</span>: self.thread_it(<span class="keyword">lambda</span>: self.update_page_url(option=<span class="number">2</span>, reg_url=<span class="string">&#x27;&#x27;</span>)))</span><br><span class="line">        menu.grid(row=<span class="number">0</span>, column=<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 添加一个标签，并将其列设置为1，行设置为0</span></span><br><span class="line">        <span class="comment"># 中间的下拉框</span></span><br><span class="line">        page = StringVar()</span><br><span class="line">        <span class="comment"># 这里直接定义成为类的属性,以便于其他方法中直接获取其选择的页数</span></span><br><span class="line">        self.page_chosen = ttk.Combobox(self.indo, width=<span class="number">12</span>, textvariable=page)</span><br><span class="line">        self.page_chosen[<span class="string">&#x27;values&#x27;</span>] = <span class="built_in">tuple</span>(<span class="built_in">range</span>(<span class="number">1</span>, self.page_max + <span class="number">1</span>))  <span class="comment"># 设置下拉列表的值</span></span><br><span class="line">        <span class="comment"># 设置其在界面中出现的位置 column代表列 row 代表行</span></span><br><span class="line">        self.page_chosen.grid(row=<span class="number">2</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        <span class="comment"># 设置下拉列表默认显示的值，0为 numberChosen[&#x27;values&#x27;] 的下标值</span></span><br><span class="line">        self.page_chosen.current(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        menu = Button(self.indo, text=<span class="string">&quot; 跳转到此页 &quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>),background = <span class="string">&#x27;gray&#x27;</span>,</span><br><span class="line">                      command=<span class="keyword">lambda</span>: self.update_page_url(option=<span class="number">3</span>, reg_url=<span class="string">&#x27;&#x27;</span>))</span><br><span class="line">        menu.grid(row=<span class="number">3</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 用于指定下载路径</span></span><br><span class="line">        Tk_gui.path = StringVar()</span><br><span class="line">        <span class="comment">#</span></span><br><span class="line">        Label(self.indo, text=<span class="string">&quot;目标路径:&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>)). \</span><br><span class="line">            grid(row=<span class="number">9</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        Entry(self.indo, textvariable=self.path, width=<span class="number">15</span>). \</span><br><span class="line">            grid(row=<span class="number">10</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        Button(self.indo, text=<span class="string">&quot;更改下载路径&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>, command=self.get_save_path). \</span><br><span class="line">            grid(row=<span class="number">11</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 初始化保存路径</span></span><br><span class="line">        Tk_gui.path.<span class="built_in">set</span>(path.dirname(__file__))</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">stat_info</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 外加的详细下载信息栏</span></span><br><span class="line">        <span class="comment"># 定义成类属性,以便于在Spider类中更改其值</span></span><br><span class="line">        Tk_gui.stat_info = Label(self.stat, text=<span class="string">&#x27;&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                                     font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>))</span><br><span class="line">        Tk_gui.stat_info.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        Tk_gui.stat_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Spider</span>():</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">pre_download</span>(<span class="params">self, meizi_url</span>):</span></span><br><span class="line">        self.headers = &#123;</span><br><span class="line">            <span class="string">&#x27;Referer&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;user-agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment"># print(self.meizi_url)</span></span><br><span class="line">        meizi_html = get(meizi_url, headers=self.headers).text</span><br><span class="line">        end_url = findall(<span class="string">&quot;&lt;span&gt;(\d+?)&lt;/span&gt;&lt;/a&gt;&lt;a href=&#x27;https://www.mzitu.com/\d*?/2&#x27;&gt;&lt;span&gt;下一页&amp;raquo&quot;</span>, meizi_html)</span><br><span class="line">        name_id = search(<span class="string">&#x27;&lt;h2 class=&quot;main-title&quot;&gt;(.*?)&lt;/h2&gt;&#x27;</span>, meizi_html).group(<span class="number">1</span>)</span><br><span class="line">        name = sub(<span class="string">&#x27;!&#x27;</span>, <span class="string">&#x27;&#x27;</span>, name_id)</span><br><span class="line">        print(<span class="string">&quot;本页的总数:&quot;</span>)</span><br><span class="line">        end_url = <span class="built_in">int</span>(end_url[<span class="number">0</span>])</span><br><span class="line">        print(end_url)</span><br><span class="line">        <span class="keyword">return</span> end_url, name, meizi_url</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">ori_video</span>(<span class="params">self, end_url, name, meizi_url</span>):</span></span><br><span class="line">        <span class="comment"># 获取用户选择的路径</span></span><br><span class="line">        choose_dir = Tk_gui.path.get()</span><br><span class="line">        <span class="comment"># print(&#x27;选择的路径：&#x27;, choose_dir)</span></span><br><span class="line">        <span class="comment"># 判断文件夹是否存在</span></span><br><span class="line">        <span class="comment"># print(&#x27;lsitdir&#x27;, listdir(choose_dir))</span></span><br><span class="line">        <span class="comment"># name = choose_dir + &#x27;/&#x27; + name</span></span><br><span class="line"></span><br><span class="line">        curr_dir = choose_dir + <span class="string">&#x27;/&#x27;</span> + name</span><br><span class="line">        <span class="keyword">for</span> x <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, end_url + <span class="number">1</span>):</span><br><span class="line">            <span class="comment"># 更新详情信息的内容</span></span><br><span class="line">            Tk_gui.terminal_info[<span class="string">&quot;text&quot;</span>] = \</span><br><span class="line">                <span class="string">&#x27;正在下载图片...\t&#x27;</span> + <span class="string">&#x27;当前进度:&#x27;</span> + <span class="built_in">str</span>(x) + <span class="string">&#x27; / &#x27;</span> + <span class="built_in">str</span>(end_url)</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> name <span class="keyword">not</span> <span class="keyword">in</span> listdir(choose_dir):</span><br><span class="line">                mkdir(curr_dir)</span><br><span class="line">                Tk_gui.terminal_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;创建文件夹:&#x27;</span>+ curr_dir</span><br><span class="line">            self.single(x, name, meizi_url, curr_dir)</span><br><span class="line">        Tk_gui.terminal_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;图片下载完成,成功保存到&#x27;</span>+curr_dir[<span class="number">0</span>:<span class="number">25</span>]+<span class="string">&#x27;...&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">single</span>(<span class="params">self, x, name, meizi_url, curr_dir</span>):</span></span><br><span class="line">        newurl = meizi_url + <span class="string">&#x27;/&#x27;</span> + <span class="built_in">str</span>(x)</span><br><span class="line"></span><br><span class="line">        html = get(newurl, headers=self.headers).text</span><br><span class="line">        end_re = findall(<span class="string">r&#x27;&lt;div class=&quot;main-image&quot;&gt;&lt;p&gt;&lt;a href=&quot;.+?&quot; &gt;&lt;img src=&quot;(.*?)&quot;&#x27;</span>, html)</span><br><span class="line">        print(end_re[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line">        <span class="comment"># urlretrieve(end_re[0],path+&#x27;/&#x27;+ str(x)) 不能加请求头</span></span><br><span class="line">        req = Request(end_re[<span class="number">0</span>], headers=self.headers)</span><br><span class="line">        response = urlopen(req)</span><br><span class="line">        fname = end_re[<span class="number">0</span>].split(<span class="string">&#x27;/&#x27;</span>)[-<span class="number">1</span>]</span><br><span class="line">        print(<span class="string">&#x27;正在下载: &#x27;</span>, fname)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 文件夹名字前面加上所选择的路径</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(curr_dir + <span class="string">&#x27;/&#x27;</span> + fname, <span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            f.write(response.read())</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27; 反反爬  设置时间间隔 防止服务器封锁IP或禁止访问&#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># sleep(1)</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">page_one</span>(<span class="params">self, url</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        # 下载一页的内容</span></span><br><span class="line"><span class="string">        :param url:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># url = &#x27;https://www.mzitu.com/&#x27;</span></span><br><span class="line">        <span class="comment"># url = &#x27;https://www.mzitu.com/page/2/&#x27;</span></span><br><span class="line">        headers = &#123;</span><br><span class="line">            <span class="string">&#x27;Referer&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;user-agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        html = get(url, headers=headers).text</span><br><span class="line">        <span class="comment"># print(html)</span></span><br><span class="line">        ret = findall(<span class="string">&#x27;&lt;li&gt;&lt;a href=&quot;(.*?)&quot; target=&quot;_blank&quot;&gt;&lt;img class=&#x27;</span>, html)</span><br><span class="line">        tit = findall(<span class="string">&quot;&lt;li&gt;&lt;a.*?alt=\&#x27;(.*?)\&#x27;&quot;</span>, html)</span><br><span class="line">        <span class="keyword">return</span> ret, tit</span><br><span class="line"></span><br><span class="line"><span class="comment"># 实例化对象</span></span><br><span class="line">s = Spider()</span><br><span class="line">t = Tk_gui()</span><br></pre></td></tr></table></figure><h3 id="相关阅读"><a href="#相关阅读" class="headerlink" title="相关阅读"></a>相关阅读</h3><p><a href="https://blog.csdn.net/qq_40223983/article/details/96857832">python爬取梨视频</a></p><p><a href="https://blog.csdn.net/qq_40223983/article/details/96310326">python爬取有道翻译</a></p><h3 id="维护"><a href="#维护" class="headerlink" title="维护"></a>维护</h3><blockquote><p>mzitu网站加了一个类导致原来的正则不正确</p><p>修复如下</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by victor</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;带有图形界面的妹子图爬虫程序&gt;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">加入了顶部颜色的更改,实现了排它思想</span></span><br><span class="line"><span class="string">下载按钮在下载中的按钮颜色更改</span></span><br><span class="line"><span class="string">加上了 一个顶部的转台信息栏</span></span><br><span class="line"><span class="string">加入了多线程功能,解决了在下载过程中图形界面卡顿问题</span></span><br><span class="line"><span class="string">TODO 显示预览图</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 导包</span></span><br><span class="line"><span class="keyword">from</span> tkinter <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> tkinter <span class="keyword">import</span> ttk</span><br><span class="line"><span class="keyword">from</span> tkinter.filedialog <span class="keyword">import</span> askdirectory</span><br><span class="line"><span class="keyword">from</span> requests <span class="keyword">import</span> get</span><br><span class="line"><span class="keyword">from</span> re <span class="keyword">import</span> findall</span><br><span class="line"><span class="keyword">from</span> re <span class="keyword">import</span> search</span><br><span class="line"><span class="keyword">from</span> re <span class="keyword">import</span> sub</span><br><span class="line"><span class="keyword">from</span> os <span class="keyword">import</span> listdir</span><br><span class="line"><span class="keyword">from</span> os <span class="keyword">import</span> mkdir</span><br><span class="line"><span class="keyword">from</span> os <span class="keyword">import</span> path</span><br><span class="line"><span class="keyword">from</span> urllib.request <span class="keyword">import</span> Request</span><br><span class="line"><span class="keyword">from</span> urllib.request <span class="keyword">import</span> urlopen</span><br><span class="line"><span class="keyword">from</span> time <span class="keyword">import</span> sleep</span><br><span class="line"><span class="keyword">from</span> threading <span class="keyword">import</span> Thread</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Tk_gui</span>():</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        初始化魔术方法</span></span><br><span class="line"><span class="string">        用于设置界面的初始状态</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 创建tkinter窗口</span></span><br><span class="line">        self.root = Tk()</span><br><span class="line">        <span class="comment"># 设置窗口的标题</span></span><br><span class="line">        self.root.title(<span class="string">&#x27;一起来看美女&#x27;</span>)</span><br><span class="line">        <span class="comment"># 设置窗口的长和宽,最大值和最小值设置相同,用户不可调整窗口大小</span></span><br><span class="line">        self.root.minsize(<span class="number">780</span>, <span class="number">370</span>)</span><br><span class="line">        self.root.maxsize(<span class="number">780</span>, <span class="number">570</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 初始化</span></span><br><span class="line">        self.curr_page = <span class="number">1</span></span><br><span class="line">        self.page_max = self.get_page_max()</span><br><span class="line">        <span class="comment"># 初始化主要url</span></span><br><span class="line">        self.curr_url = <span class="string">&#x27;https://www.mzitu.com/&#x27;</span></span><br><span class="line">        self.tit_list = s.page_one(self.curr_url)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 调用主要逻辑执行函数</span></span><br><span class="line">        self.main_logic()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">thread_it</span>(<span class="params">self, func, *args</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        将函数打包进线程</span></span><br><span class="line"><span class="string">        :param func:</span></span><br><span class="line"><span class="string">        :param args:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 创建</span></span><br><span class="line">        t = Thread(target=func, args=args)</span><br><span class="line">        <span class="comment"># 守护 !!!</span></span><br><span class="line">        t.setDaemon(<span class="literal">True</span>)</span><br><span class="line">        <span class="comment"># 启动</span></span><br><span class="line">        t.start()</span><br><span class="line">        <span class="comment"># 阻塞--卡死界面！</span></span><br><span class="line">        <span class="comment"># t.join()</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_save_path</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        path_ = askdirectory()</span><br><span class="line">        Tk_gui.path.<span class="built_in">set</span>(path_)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_page_max</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">50</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">main_logic</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        主业务逻辑</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 顶部信息栏</span></span><br><span class="line">        topp = Frame()</span><br><span class="line">        topp.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 内容栏</span></span><br><span class="line">        self.cont = Frame()</span><br><span class="line">        self.cont.grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 输入选项操作</span></span><br><span class="line">        self.indo = Frame()</span><br><span class="line">        self.indo.grid(row=<span class="number">0</span>, column=<span class="number">1</span>, rowspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 状态栏</span></span><br><span class="line">        self.stat = Frame()</span><br><span class="line">        self.stat.grid(row=<span class="number">2</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        self.top_menu(topp)</span><br><span class="line">        self.stat_info()</span><br><span class="line">        self.main_content(self.get_num_list())</span><br><span class="line"></span><br><span class="line">        self.get_title_list(<span class="string">&#x27;https://www.mzitu.com&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 加入主消息循环</span></span><br><span class="line">        self.root.mainloop()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">download</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        正式下载图片</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        self.btn5[<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;pink&#x27;</span></span><br><span class="line">        para = self.search()</span><br><span class="line">        s.ori_video(para[<span class="number">0</span>], para[<span class="number">1</span>], para[<span class="number">2</span>])</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">search</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        搜索预加载页面中的图片个数</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># print(&quot;下载url:&quot;)</span></span><br><span class="line">        index = <span class="built_in">int</span>(self.number_chosen.get()) - <span class="number">1</span></span><br><span class="line">        <span class="comment"># print(&#x27;index:%d&#x27;%index)</span></span><br><span class="line">        url = tit_list[<span class="number">0</span>][index]</span><br><span class="line">        para = s.pre_download(url)</span><br><span class="line">        self.detail_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&quot;本页有&quot;</span> + <span class="built_in">str</span>(para[<span class="number">0</span>]) + <span class="string">&quot;张图&quot;</span></span><br><span class="line">        <span class="keyword">return</span> para</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_title_list</span>(<span class="params">self, url</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        获取标题列表内容</span></span><br><span class="line"><span class="string">        :param url:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="keyword">global</span> tit_list</span><br><span class="line">        tit_list = s.page_one(url)</span><br><span class="line">        self.info[<span class="string">&quot;text&quot;</span>] = <span class="string">&quot;\n&quot;</span>.join(tit_list[<span class="number">1</span>])</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_num_list</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        获取数值列表</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        num = []</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">25</span>):</span><br><span class="line">            num.append(<span class="built_in">str</span>(i))</span><br><span class="line">        num_str = <span class="string">&quot;\n&quot;</span>.join(num)</span><br><span class="line">        <span class="keyword">return</span> num_str</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">set_top_bg</span>(<span class="params">self, <span class="built_in">id</span></span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :param id: id 是按钮摆放的位置,int类型的</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># 还原现场</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> self.button_list:</span><br><span class="line">            i[<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;skyblue&#x27;</span></span><br><span class="line"></span><br><span class="line">        self.button_list[<span class="built_in">id</span> - <span class="number">1</span>][<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;pink&#x27;</span></span><br><span class="line">        <span class="comment"># for i in</span></span><br><span class="line">        <span class="comment">#     if curr == i:</span></span><br><span class="line">        <span class="comment">#         i[&#x27;bg&#x27;]==&#x27;gray&#x27;</span></span><br><span class="line">        <span class="comment">#     else:</span></span><br><span class="line">        <span class="comment">#         i[&#x27;bg&#x27;]==&#x27;&#x27;</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">update_page_url</span>(<span class="params">self, option, reg_url</span>):</span></span><br><span class="line">        <span class="keyword">if</span> option:</span><br><span class="line">            <span class="keyword">if</span> option == <span class="number">2</span>:</span><br><span class="line">                print(<span class="string">&#x27;下一页&#x27;</span>)</span><br><span class="line">                <span class="keyword">if</span> self.curr_page &lt; self.page_max:</span><br><span class="line">                    self.curr_page += <span class="number">1</span></span><br><span class="line">            <span class="keyword">elif</span> option == <span class="number">1</span>:</span><br><span class="line">                print(<span class="string">&#x27;上一页&#x27;</span>)</span><br><span class="line">                <span class="keyword">if</span> self.curr_page &gt; <span class="number">1</span>:</span><br><span class="line">                    self.curr_page -= <span class="number">1</span></span><br><span class="line">            <span class="keyword">elif</span> option == <span class="number">3</span>:</span><br><span class="line">                self.curr_page = <span class="built_in">int</span>(self.page_chosen.get())</span><br><span class="line">        <span class="keyword">if</span> reg_url:</span><br><span class="line">            <span class="comment"># TODO 设置更新按钮的背景颜色</span></span><br><span class="line">            <span class="comment"># 调用set_button_color</span></span><br><span class="line">            <span class="comment"># 重置页面数</span></span><br><span class="line">            self.curr_page = <span class="number">1</span></span><br><span class="line">            self.curr_url = reg_url</span><br><span class="line">        <span class="keyword">if</span> self.curr_page == <span class="number">1</span>:</span><br><span class="line">            url = self.curr_url</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            url = self.curr_url + <span class="string">&#x27;page/&#x27;</span> + <span class="built_in">str</span>(self.curr_page) + <span class="string">&#x27;/&#x27;</span></span><br><span class="line">        print(self.curr_page)</span><br><span class="line">        self.page_info[<span class="string">&#x27;text&#x27;</span>] = <span class="string">&#x27;当前页数:&#x27;</span> + <span class="built_in">str</span>(self.curr_page)</span><br><span class="line">        self.get_title_list(url)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">top_menu</span>(<span class="params">self, topp</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        用于绘制顶部菜单</span></span><br><span class="line"><span class="string">        :param topp:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        self.button_list = []</span><br><span class="line">        <span class="comment"># 菜单栏</span></span><br><span class="line">        url_list = &#123;</span><br><span class="line">            <span class="string">&#x27;推荐&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;性感&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/xinggan/&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;日本&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/japan/&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;台湾&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/taiwan/&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;清纯&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com/mm/&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment"># update_page_url函数是用来更新页面的内容以及后面要下载的url的</span></span><br><span class="line">        menu = Button(topp, text=<span class="string">&#x27;&#x27;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">1</span>)</span><br><span class="line">        menu.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">put_button</span>(<span class="params">key, col</span>):</span></span><br><span class="line">            <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">            用于画出按钮组件</span></span><br><span class="line"><span class="string">            :param contain:按钮显示的文本内容</span></span><br><span class="line"><span class="string">            :param key: 命令执行的函数选择的键</span></span><br><span class="line"><span class="string">            :param col: 按钮放置的列数</span></span><br><span class="line"><span class="string">            :return:</span></span><br><span class="line"><span class="string">            &#x27;&#x27;&#x27;</span></span><br><span class="line">            <span class="comment"># self.curr_button = StringVar()</span></span><br><span class="line">            <span class="comment"># TODO 怎么解决一个command 执行两个函数的问题</span></span><br><span class="line">            <span class="comment"># 这里用is机制的占了个位置,让两个函数都执行,随便返回点啥,我都不要,哈哈哈哈哈</span></span><br><span class="line">            <span class="comment"># 之前尝试过用函数的参数传递,但是有点不太好管理</span></span><br><span class="line">            <span class="comment"># 后来用的+号,程序报错,虽然界面中看不出来,但是我还是有点强迫症的让他不报错</span></span><br><span class="line">            self.menu = Button(topp, text=key, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">7</span>, \</span><br><span class="line">                               command=<span class="keyword">lambda</span>: self.update_page_url(option=<span class="number">0</span>, reg_url=url_list[key]) <span class="keyword">is</span> \</span><br><span class="line">                                               self.set_top_bg(col))</span><br><span class="line"></span><br><span class="line">            self.menu.grid(row=<span class="number">0</span>, column=col)</span><br><span class="line">            self.button_list.append(self.menu)</span><br><span class="line">            <span class="keyword">for</span> i <span class="keyword">in</span> self.button_list:</span><br><span class="line">                i[<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;skyblue&#x27;</span></span><br><span class="line">            self.button_list[<span class="number">0</span>][<span class="string">&#x27;background&#x27;</span>] = <span class="string">&#x27;pink&#x27;</span></span><br><span class="line">            <span class="comment"># if key == self.curr_button:</span></span><br><span class="line">            <span class="comment">#     menu[&#x27;background&#x27;] = &#x27;gray&#x27;</span></span><br><span class="line"></span><br><span class="line">        i = <span class="number">1</span></span><br><span class="line">        <span class="keyword">for</span> contain <span class="keyword">in</span> url_list.keys():</span><br><span class="line">            put_button(contain, i)</span><br><span class="line">            i += <span class="number">1</span></span><br><span class="line">        <span class="comment">#</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 前进和后退,进行页数的更改</span></span><br><span class="line">        <span class="comment"># option为标记位,0为不改变</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 顶部的显示当前页数的lable</span></span><br><span class="line">        <span class="comment"># 定义成类属性,以便于在Spider类中更改其值</span></span><br><span class="line">        self.page_info = Label(topp, text=<span class="string">&#x27;&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                               font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">10</span>)</span><br><span class="line">        self.page_info.grid(row=<span class="number">0</span>, column=<span class="number">6</span>)</span><br><span class="line"></span><br><span class="line">        self.page_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;当前页数:1&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">main_content</span>(<span class="params">self, num_str</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        主要内容界面,包括数字列表的显示,标题列表的显示以及右边输入框和下载按钮部分</span></span><br><span class="line"><span class="string">        :param num_str:数字列表显示内容</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 左边的序号栏</span></span><br><span class="line">        one = Label(self.cont, text=num_str, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), relief=<span class="string">&#x27;ridge&#x27;</span>)</span><br><span class="line">        one.grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        <span class="comment"># 中间的主要信息栏</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        relief(可选值为：flat(默认),sunken,raised,groove,ridge)，borderwidth(边框的宽度，单位是像素，默认根据系统而定，一般是1或2像素)</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        self.info = Label(self.cont, text=<span class="string">&#x27;info&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                          font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">49</span>, relief=<span class="string">&#x27;ridge&#x27;</span>)</span><br><span class="line">        self.info.grid(row=<span class="number">1</span>, column=<span class="number">1</span>, columnspan=<span class="number">6</span>)</span><br><span class="line">        <span class="comment"># 右边的选择栏</span></span><br><span class="line">        <span class="comment"># 上面的提升lable</span></span><br><span class="line">        ttk.Label(self.indo, text=<span class="string">&quot;\n\n\n选择一个&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>)).grid(column=<span class="number">0</span>, row=<span class="number">4</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        <span class="comment"># 添加一个标签，并将其列设置为1，行设置为0</span></span><br><span class="line">        <span class="comment"># 中间的下拉框</span></span><br><span class="line">        number = StringVar()</span><br><span class="line">        <span class="comment"># 这里直接定义成为类的属性,以便于其他方法中直接获取其选择的页数</span></span><br><span class="line">        self.number_chosen = ttk.Combobox(self.indo, width=<span class="number">12</span>, textvariable=number)</span><br><span class="line">        self.number_chosen[<span class="string">&#x27;values&#x27;</span>] = <span class="built_in">tuple</span>(<span class="built_in">range</span>(<span class="number">1</span>, <span class="number">25</span>))  <span class="comment"># 设置下拉列表的值</span></span><br><span class="line">        self.number_chosen.grid(column=<span class="number">0</span>, row=<span class="number">5</span>, columnspan=<span class="number">2</span>)  <span class="comment"># 设置其在界面中出现的位置 column代表列 row 代表行</span></span><br><span class="line">        self.number_chosen.current(<span class="number">0</span>)  <span class="comment"># 设置下拉列表默认显示的值，0为 numberChosen[&#x27;values&#x27;] 的下标值</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 由于进行了类的封装,所以不需要借用列表的穿透性了</span></span><br><span class="line">        <span class="comment"># 直接定义一个类的成员属性即可传递到类中的任何位置</span></span><br><span class="line">        <span class="comment"># 这里实时更新当前选中的数字内容,以便于按下下载按钮时能够定位到准确的页面</span></span><br><span class="line">        <span class="comment"># TODO 可以优化到其他位置,减少功能模块之间的耦合性</span></span><br><span class="line">        <span class="comment"># self.user_choose_num = self.number_chosen.get()</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 点击查询按钮</span></span><br><span class="line">        btn4 = Button(self.indo, text=<span class="string">&quot;查询图片个数&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>,</span><br><span class="line">                      command=<span class="keyword">lambda</span>: self.thread_it(self.search))</span><br><span class="line">        btn4.grid(column=<span class="number">0</span>, row=<span class="number">6</span>, columnspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 外加的详细信息栏</span></span><br><span class="line">        <span class="comment"># 这里直接定义成为类的属性,以便于其他方法中直接修改其内容</span></span><br><span class="line">        self.detail_info = Label(self.indo, text=<span class="string">&#x27;&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                                 font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), width=<span class="number">10</span>)</span><br><span class="line">        self.detail_info.grid(row=<span class="number">7</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        <span class="comment"># 点击下载的按钮</span></span><br><span class="line">        self.btn5 = Button(self.indo, text=<span class="string">&quot;下载此页图片&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>,</span><br><span class="line">                           command=<span class="keyword">lambda</span>: self.thread_it(self.download))</span><br><span class="line">        self.btn5.grid(column=<span class="number">0</span>, row=<span class="number">12</span>, columnspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 外加的详细下载信息栏</span></span><br><span class="line">        <span class="comment"># 定义成类属性,以便于在Spider类中更改其值</span></span><br><span class="line">        Tk_gui.terminal_info = Label(self.stat, text=<span class="string">&#x27;&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                                     font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>))</span><br><span class="line">        Tk_gui.terminal_info.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        Tk_gui.terminal_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">        menu = Button(self.indo, text=<span class="string">&quot; 上一页&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>,</span><br><span class="line">                      command=<span class="keyword">lambda</span>: self.thread_it(<span class="keyword">lambda</span>: self.update_page_url(option=<span class="number">1</span>, reg_url=<span class="string">&#x27;&#x27;</span>)))</span><br><span class="line">        menu.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        menu = Button(self.indo, text=<span class="string">&quot;下一页 &quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>,</span><br><span class="line">                      command=<span class="keyword">lambda</span>: self.thread_it(<span class="keyword">lambda</span>: self.update_page_url(option=<span class="number">2</span>, reg_url=<span class="string">&#x27;&#x27;</span>)))</span><br><span class="line">        menu.grid(row=<span class="number">0</span>, column=<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 添加一个标签，并将其列设置为1，行设置为0</span></span><br><span class="line">        <span class="comment"># 中间的下拉框</span></span><br><span class="line">        page = StringVar()</span><br><span class="line">        <span class="comment"># 这里直接定义成为类的属性,以便于其他方法中直接获取其选择的页数</span></span><br><span class="line">        self.page_chosen = ttk.Combobox(self.indo, width=<span class="number">12</span>, textvariable=page)</span><br><span class="line">        self.page_chosen[<span class="string">&#x27;values&#x27;</span>] = <span class="built_in">tuple</span>(<span class="built_in">range</span>(<span class="number">1</span>, self.page_max + <span class="number">1</span>))  <span class="comment"># 设置下拉列表的值</span></span><br><span class="line">        <span class="comment"># 设置其在界面中出现的位置 column代表列 row 代表行</span></span><br><span class="line">        self.page_chosen.grid(row=<span class="number">2</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        <span class="comment"># 设置下拉列表默认显示的值，0为 numberChosen[&#x27;values&#x27;] 的下标值</span></span><br><span class="line">        self.page_chosen.current(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        menu = Button(self.indo, text=<span class="string">&quot; 跳转到此页 &quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>,</span><br><span class="line">                      command=<span class="keyword">lambda</span>: self.update_page_url(option=<span class="number">3</span>, reg_url=<span class="string">&#x27;&#x27;</span>))</span><br><span class="line">        menu.grid(row=<span class="number">3</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 用于指定下载路径</span></span><br><span class="line">        Tk_gui.path = StringVar()</span><br><span class="line">        <span class="comment">#</span></span><br><span class="line">        Label(self.indo, text=<span class="string">&quot;目标路径:&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>)). \</span><br><span class="line">            grid(row=<span class="number">9</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        Entry(self.indo, textvariable=self.path, width=<span class="number">15</span>). \</span><br><span class="line">            grid(row=<span class="number">10</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line">        Button(self.indo, text=<span class="string">&quot;更改下载路径&quot;</span>, font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>), background=<span class="string">&#x27;gray&#x27;</span>, command=self.get_save_path). \</span><br><span class="line">            grid(row=<span class="number">11</span>, column=<span class="number">0</span>, columnspan=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 初始化保存路径</span></span><br><span class="line">        Tk_gui.path.<span class="built_in">set</span>(path.dirname(__file__))</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">stat_info</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 外加的详细下载信息栏</span></span><br><span class="line">        <span class="comment"># 定义成类属性,以便于在Spider类中更改其值</span></span><br><span class="line">        Tk_gui.stat_info = Label(self.stat, text=<span class="string">&#x27;&#x27;</span>, justify=<span class="string">&quot;left&quot;</span>, \</span><br><span class="line">                                 font=(<span class="string">&quot;Arial&quot;</span>, <span class="number">12</span>))</span><br><span class="line">        Tk_gui.stat_info.grid(row=<span class="number">0</span>, column=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        Tk_gui.stat_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Spider</span>():</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">pre_download</span>(<span class="params">self, meizi_url</span>):</span></span><br><span class="line">        self.headers = &#123;</span><br><span class="line">            <span class="string">&#x27;Referer&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;user-agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment"># print(self.meizi_url)</span></span><br><span class="line">        meizi_html = get(meizi_url, headers=self.headers).text</span><br><span class="line">        end_url = findall(<span class="string">&quot;&lt;span&gt;(\d+?)&lt;/span&gt;&lt;/a&gt;&lt;a href=&#x27;https://www.mzitu.com/\d*?/2&#x27;&gt;&lt;span&gt;下一页&amp;raquo&quot;</span>, meizi_html)</span><br><span class="line">        name_id = search(<span class="string">&#x27;&lt;h2 class=&quot;main-title&quot;&gt;(.*?)&lt;/h2&gt;&#x27;</span>, meizi_html).group(<span class="number">1</span>)</span><br><span class="line">        name = sub(<span class="string">&#x27;!&#x27;</span>, <span class="string">&#x27;&#x27;</span>, name_id)</span><br><span class="line">        print(<span class="string">&quot;本页的总数:&quot;</span>)</span><br><span class="line">        end_url = <span class="built_in">int</span>(end_url[<span class="number">0</span>])</span><br><span class="line">        print(end_url)</span><br><span class="line">        <span class="keyword">return</span> end_url, name, meizi_url</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">ori_video</span>(<span class="params">self, end_url, name, meizi_url</span>):</span></span><br><span class="line">        <span class="comment"># 获取用户选择的路径</span></span><br><span class="line">        choose_dir = Tk_gui.path.get()</span><br><span class="line">        <span class="comment"># print(&#x27;选择的路径：&#x27;, choose_dir)</span></span><br><span class="line">        <span class="comment"># 判断文件夹是否存在</span></span><br><span class="line">        <span class="comment"># print(&#x27;lsitdir&#x27;, listdir(choose_dir))</span></span><br><span class="line">        <span class="comment"># name = choose_dir + &#x27;/&#x27; + name</span></span><br><span class="line"></span><br><span class="line">        curr_dir = choose_dir + <span class="string">&#x27;/&#x27;</span> + name</span><br><span class="line">        <span class="keyword">for</span> x <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, end_url + <span class="number">1</span>):</span><br><span class="line">            <span class="comment"># 更新详情信息的内容</span></span><br><span class="line">            Tk_gui.terminal_info[<span class="string">&quot;text&quot;</span>] = \</span><br><span class="line">                <span class="string">&#x27;正在下载图片...\t&#x27;</span> + <span class="string">&#x27;当前进度:&#x27;</span> + <span class="built_in">str</span>(x) + <span class="string">&#x27; / &#x27;</span> + <span class="built_in">str</span>(end_url)</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> name <span class="keyword">not</span> <span class="keyword">in</span> listdir(choose_dir):</span><br><span class="line">                mkdir(curr_dir)</span><br><span class="line">                Tk_gui.terminal_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;创建文件夹:&#x27;</span> + curr_dir</span><br><span class="line">            self.single(x, name, meizi_url, curr_dir)</span><br><span class="line">        Tk_gui.terminal_info[<span class="string">&quot;text&quot;</span>] = <span class="string">&#x27;图片下载完成,成功保存到&#x27;</span> + curr_dir[<span class="number">0</span>:<span class="number">25</span>] + <span class="string">&#x27;...&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">single</span>(<span class="params">self, x, name, meizi_url, curr_dir</span>):</span></span><br><span class="line">        newurl = meizi_url + <span class="string">&#x27;/&#x27;</span> + <span class="built_in">str</span>(x)</span><br><span class="line"></span><br><span class="line">        html = get(newurl, headers=self.headers).text</span><br><span class="line">        print(html)</span><br><span class="line">        end_re = findall(<span class="string">r&#x27;&lt;div class=&quot;main-image&quot;&gt;&lt;p&gt;&lt;a href=&quot;.+?&quot; &gt;&lt;img class=&quot;blur&quot; src=&quot;(.*?)&quot;&#x27;</span>, html)</span><br><span class="line">        print(<span class="string">&quot;end_re&gt;&gt;&gt;&quot;</span>,end_re)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># urlretrieve(end_re[0],path+&#x27;/&#x27;+ str(x)) 不能加请求头</span></span><br><span class="line">        req = Request(end_re[<span class="number">0</span>], headers=self.headers)</span><br><span class="line">        response = urlopen(req)</span><br><span class="line">        fname = end_re[<span class="number">0</span>].split(<span class="string">&#x27;/&#x27;</span>)[-<span class="number">1</span>]</span><br><span class="line">        print(<span class="string">&#x27;正在下载: &#x27;</span>, fname)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 文件夹名字前面加上所选择的路径</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(curr_dir + <span class="string">&#x27;/&#x27;</span> + fname, <span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            f.write(response.read())</span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27; 反反爬  设置时间间隔 防止服务器封锁IP或禁止访问&#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># sleep(1)</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">page_one</span>(<span class="params">self, url</span>):</span></span><br><span class="line">        <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">        # 下载一页的内容</span></span><br><span class="line"><span class="string">        :param url:</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line">        <span class="comment"># url = &#x27;https://www.mzitu.com/&#x27;</span></span><br><span class="line">        <span class="comment"># url = &#x27;https://www.mzitu.com/page/2/&#x27;</span></span><br><span class="line">        headers = &#123;</span><br><span class="line">            <span class="string">&#x27;Referer&#x27;</span>: <span class="string">&#x27;https://www.mzitu.com&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;user-agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        html = get(url, headers=headers).text</span><br><span class="line">        <span class="comment"># print(html)</span></span><br><span class="line">        ret = findall(<span class="string">&#x27;&lt;li&gt;&lt;a href=&quot;(.*?)&quot; target=&quot;_blank&quot;&gt;&lt;img class=&#x27;</span>, html)</span><br><span class="line">        tit = findall(<span class="string">&quot;&lt;li&gt;&lt;a.*?alt=\&#x27;(.*?)\&#x27;&quot;</span>, html)</span><br><span class="line">        <span class="keyword">return</span> ret, tit</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 实例化对象</span></span><br><span class="line">s = Spider()</span><br><span class="line">t = Tk_gui()</span><br></pre></td></tr></table></figure><h2 id="打包exe"><a href="#打包exe" class="headerlink" title="打包exe"></a>打包exe</h2><blockquote><p>可以用pyinstaller 打包成exe ,这样就可以脱离python环境运行了</p></blockquote><h2 id="图片展示"><a href="#图片展示" class="headerlink" title="图片展示"></a>图片展示</h2><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210312233035.png"></p><h3 id="日志中可以显示当前进度"><a href="#日志中可以显示当前进度" class="headerlink" title="日志中可以显示当前进度"></a>日志中可以显示当前进度</h3><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210312232813.png"></p><h3 id="你会看着文件夹中图片变多"><a href="#你会看着文件夹中图片变多" class="headerlink" title="你会看着文件夹中图片变多"></a>你会看着文件夹中图片变多</h3><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210312233012.png"><br><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210312233229.png"></p><h3 id="还可以选择翻页"><a href="#还可以选择翻页" class="headerlink" title="还可以选择翻页"></a>还可以选择翻页</h3><p><img src= "/img/loading.gif" data-lazy-src="QQ%E6%88%AA%E5%9B%BE20210312233253.png"></p><h2 id="源"><a href="#源" class="headerlink" title="源"></a>源</h2><p>exe下载路径: <a href="https://gitee.com/victorfengming/python_projects/blob/master/meizi_spider/meizi_spider7.1.exe">meizi_spider.exe</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> spider </tag>
            
            <tag> tkinter </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算器</title>
      <link href="python/GUI/tkinter/tkinter-calculator/"/>
      <url>python/GUI/tkinter/tkinter-calculator/</url>
      
        <content type="html"><![CDATA[<h3 id="面向过程开发"><a href="#面向过程开发" class="headerlink" title="面向过程开发"></a>面向过程开发</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by xiaoming</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># from .. import 花里胡哨</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># strr = input(&#x27;请输入:&#x27;)</span></span><br><span class="line"><span class="comment"># eval(strr)</span></span><br><span class="line"><span class="keyword">import</span> tkinter</span><br><span class="line"></span><br><span class="line">root = tkinter.Tk()</span><br><span class="line">root.title(<span class="string">&#x27;最强计算器&#x27;</span>)</span><br><span class="line">root.minsize(<span class="number">400</span>,<span class="number">500</span>)</span><br><span class="line"></span><br><span class="line">chang = <span class="number">80</span></span><br><span class="line">kuan = <span class="number">60</span></span><br><span class="line"><span class="comment"># 计算器显示内容应该用字符串显示</span></span><br><span class="line"></span><br><span class="line">num = tkinter.StringVar()</span><br><span class="line">num.<span class="built_in">set</span>(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建label显示</span></span><br><span class="line">label = tkinter.Label(root,textvariable = num,bg = <span class="string">&#x27;white&#x27;</span>, font = (<span class="string">&#x27;黑体&#x27;</span>,<span class="number">30</span>), anchor = <span class="string">&#x27;e&#x27;</span>)</span><br><span class="line">label.place(x = <span class="number">10</span>, y = <span class="number">10</span>,width = <span class="number">380</span>, height = <span class="number">40</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">#运算标志(是否按下了运算按钮 True 按了 False没按)</span></span><br><span class="line">isys = <span class="literal">False</span></span><br><span class="line"><span class="comment"># 用于存储运算列表</span></span><br><span class="line">yslists = []</span><br><span class="line"><span class="comment"># 按钮</span></span><br><span class="line"><span class="comment"># 数字按钮操作</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">pressno</span>(<span class="params">no</span>):</span></span><br><span class="line">    <span class="comment"># print(no)</span></span><br><span class="line">    <span class="comment"># 全局变量</span></span><br><span class="line">    <span class="keyword">global</span> isys</span><br><span class="line">    <span class="comment"># 判断用户是否按下了运算按钮</span></span><br><span class="line">    <span class="keyword">if</span> isys == <span class="literal">True</span>:</span><br><span class="line">        <span class="comment"># 按下了运算按钮</span></span><br><span class="line">        num.<span class="built_in">set</span>(no)</span><br><span class="line">        <span class="comment"># 将运算标志复位</span></span><br><span class="line">        isys = <span class="literal">False</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="comment"># 没按下运算按钮</span></span><br><span class="line">        <span class="comment"># 判断原始数字是否为0</span></span><br><span class="line">        oldno = num.get()</span><br><span class="line">        <span class="keyword">if</span> oldno == <span class="string">&#x27;0&#x27;</span>:</span><br><span class="line">            <span class="comment"># 如果界面为0,如果界面不为0</span></span><br><span class="line">            num.<span class="built_in">set</span>(no)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            num.<span class="built_in">set</span>(num.get()+no)</span><br><span class="line">        <span class="comment"># 获取用户按下的数字,显示到界面中</span></span><br><span class="line">    <span class="comment"># 获取界面中的输入内容</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 运算按钮操作</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">pressys</span>(<span class="params">ysflag</span>):</span></span><br><span class="line">    <span class="keyword">global</span> isys</span><br><span class="line">    <span class="comment"># 设置运算被按下的标志</span></span><br><span class="line">    isys = <span class="literal">True</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">#将每次运算的操作的信息计入一个列表[&#x27;22&#x27;,&#x27;*&#x27;,&#x27;88&#x27;]</span></span><br><span class="line">    <span class="comment"># result = eval(&#x27;&#x27;.join([&#x27;&#x27;&#x27;&#x27;&#x27;&#x27;&#x27;]))</span></span><br><span class="line"></span><br><span class="line">    yslists.append(num.get())</span><br><span class="line">    print(yslists)</span><br><span class="line">    <span class="comment"># 计算结果</span></span><br><span class="line">    cal_res()</span><br><span class="line">    <span class="comment"># 将下一个字符添加到列表中</span></span><br><span class="line">    <span class="keyword">if</span> ysflag == <span class="string">&#x27;=&#x27;</span>:</span><br><span class="line">        yslists.clear()</span><br><span class="line">    <span class="comment"># 如果按的是符号</span></span><br><span class="line">    <span class="keyword">elif</span> ysflag == <span class="string">&#x27;clear&#x27;</span>:</span><br><span class="line">        yslists.clear()</span><br><span class="line">        num.<span class="built_in">set</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        yslists.append(ysflag)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 计算中间结果</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">cal_res</span>():</span></span><br><span class="line">    <span class="keyword">global</span> yslists</span><br><span class="line">    res = <span class="built_in">eval</span>(<span class="string">&#x27;&#x27;</span>.join(yslists))</span><br><span class="line">    print(res)</span><br><span class="line">    num.<span class="built_in">set</span>(res)</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"><span class="comment"># #</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def cls_contain():</span></span><br><span class="line"><span class="comment">#     # 清除屏幕</span></span><br><span class="line"><span class="comment">#     yslists.clear()</span></span><br><span class="line"><span class="comment">#     num.set(&#x27;&#x27;)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 定义摆放方法</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">baifang_num</span>(<span class="params">contain,com_func,x,y</span>):</span></span><br><span class="line">    btn = tkinter.Button(root,text = contain, command = <span class="keyword">lambda</span> : com_func(contain))</span><br><span class="line">    btn.place(x = chang*x, y = kuan*y, width = chang, height = kuan)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>,<span class="number">10</span>):</span><br><span class="line">    baifang_num(<span class="built_in">str</span>(i),pressno,x = (i+<span class="number">2</span>)%<span class="number">3</span>, y = <span class="number">4</span>-(i//<span class="number">3.1</span>))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 数字0</span></span><br><span class="line">baifang_num(<span class="string">&#x27;0&#x27;</span>,pressno,<span class="number">1</span>,<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 数字.</span></span><br><span class="line">baifang_num(<span class="string">&#x27;.&#x27;</span>,pressno,<span class="number">2</span>,<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 等号</span></span><br><span class="line">baifang_num(<span class="string">&#x27;=&#x27;</span>,pressys,<span class="number">3</span>,<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 加号</span></span><br><span class="line">baifang_num(<span class="string">&#x27;+&#x27;</span>,pressys,<span class="number">3</span>,<span class="number">4</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 加号</span></span><br><span class="line">baifang_num(<span class="string">&#x27;-&#x27;</span>,pressys,<span class="number">3</span>,<span class="number">3</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 加号</span></span><br><span class="line">baifang_num(<span class="string">&#x27;*&#x27;</span>,pressys,<span class="number">3</span>,<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 加号</span></span><br><span class="line">baifang_num(<span class="string">&#x27;/&#x27;</span>,pressys,<span class="number">3</span>,<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 清空</span></span><br><span class="line">baifang_num(<span class="string">&#x27;clear&#x27;</span>,pressys,<span class="number">0</span>,<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># btn2 = tkinter.Button(root,text = &#x27;0&#x27;, command = lambda : pressno(&#x27;0&#x27;))</span></span><br><span class="line"><span class="comment"># btn2.place(x = 70, y = 5*50, width = 70, height = 50)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># # 数字.</span></span><br><span class="line"><span class="comment"># btn2 = tkinter.Button(root,text = &#x27;.&#x27;, command = lambda : pressno(&#x27;.&#x27;))</span></span><br><span class="line"><span class="comment"># btn2.place(x = 70*2, y = 5*50, width = 70, height = 50)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># #等号</span></span><br><span class="line"><span class="comment"># btneq = tkinter.Button(root,text = &#x27;=&#x27;, command = lambda : pressys(&#x27;=&#x27;))</span></span><br><span class="line"><span class="comment"># btneq.place(x = 0, y = 250, width = 70, height = 50)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># # 数字2</span></span><br><span class="line"><span class="comment"># btn2 = tkinter.Button(root,text = &#x27;2&#x27;, command = lambda : pressno(&#x27;2&#x27;))</span></span><br><span class="line"><span class="comment"># btn2.place(x = 10, y = 50, width = 50, height = 50)</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># # 数字8</span></span><br><span class="line"><span class="comment"># btn8 = tkinter.Button(root,text = &#x27;8&#x27;, command = lambda : pressno(&#x27;8&#x27;))</span></span><br><span class="line"><span class="comment"># btn8.place(x = 240, y = 50, width = 50, height = 50)</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># #运算</span></span><br><span class="line"><span class="comment"># btnx = tkinter.Button(root,text = &#x27;x&#x27;, command = lambda : pressys(&#x27;*&#x27;))</span></span><br><span class="line"><span class="comment"># btnx.place(x = 10, y = 250, width = 50, height = 50)</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># #等号</span></span><br><span class="line"><span class="comment"># btneq = tkinter.Button(root,text = &#x27;=&#x27;, command = lambda : pressys(&#x27;=&#x27;))</span></span><br><span class="line"><span class="comment"># btneq.place(x = 240, y = 250, width = 50, height = 50)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 加入主消息循环</span></span><br><span class="line">root.mainloop()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="面向对象开发版本"><a href="#面向对象开发版本" class="headerlink" title="面向对象开发版本"></a>面向对象开发版本</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by xiaoming</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;计算器程序&gt;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">版本说明:</span></span><br><span class="line"><span class="string">    TODO 还有一堆BUG没搞定(多次按运算符按键,导致结果计算不对)</span></span><br><span class="line"><span class="string">    TODO 等于号多次按下进行重复运算</span></span><br><span class="line"><span class="string">    TODO 改这些儿地方太费劲了,拉倒吧</span></span><br><span class="line"><span class="string">    TODO __init__ 初始化魔术方法 使用不够熟练</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入图形化模块</span></span><br><span class="line"><span class="keyword">import</span> tkinter</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Calculation</span>:</span></span><br><span class="line">    <span class="comment"># 成员属性</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 每个按钮的大小</span></span><br><span class="line">    but_chang = <span class="number">80</span></span><br><span class="line">    but_kuan = <span class="number">60</span></span><br><span class="line">    win_chang = <span class="number">400</span></span><br><span class="line">    win_kuan = <span class="number">500</span></span><br><span class="line">    <span class="comment"># 运算标志(是否按下了运算按钮 True 按了 False没按)</span></span><br><span class="line">    isys = <span class="literal">False</span></span><br><span class="line">    <span class="comment"># 用于存储运算列表</span></span><br><span class="line">    yslist = []</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 成员方法</span></span><br><span class="line">    <span class="comment"># 初始化方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.run_logic()</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 数字按钮操作</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">press_num</span>(<span class="params">self,no</span>):</span></span><br><span class="line">        print(self.yslist)</span><br><span class="line">        <span class="comment"># 判断用户是否按下了运算按钮</span></span><br><span class="line">        <span class="keyword">if</span> self.isys == <span class="literal">True</span>:</span><br><span class="line">            <span class="comment"># 按下了运算按钮</span></span><br><span class="line">            self.num.<span class="built_in">set</span>(no)</span><br><span class="line">            <span class="comment"># 将运算标志复位</span></span><br><span class="line">            self.isys = <span class="literal">False</span></span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="comment"># 没按下运算按钮</span></span><br><span class="line">            <span class="comment"># 判断原始数字是否为0</span></span><br><span class="line">            oldno = self.num.get()</span><br><span class="line">            <span class="keyword">if</span> oldno == <span class="string">&#x27;0&#x27;</span>:</span><br><span class="line">                <span class="comment"># 如果界面为0,如果界面不为0</span></span><br><span class="line">                self.num.<span class="built_in">set</span>(no)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                self.num.<span class="built_in">set</span>(self.num.get() + no)</span><br><span class="line">            <span class="comment"># 获取用户按下的数字,显示到界面中</span></span><br><span class="line">        <span class="comment"># 获取界面中的输入内容</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 符号按钮操作</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">press_sym</span>(<span class="params">self,ysflag</span>):</span></span><br><span class="line">        <span class="comment"># 设置运算被按下的标志</span></span><br><span class="line">        self.isys = <span class="literal">True</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 将每次运算的操作的信息计入一个列表[&#x27;22&#x27;,&#x27;*&#x27;,&#x27;88&#x27;]</span></span><br><span class="line">        <span class="comment"># result = eval(&#x27;&#x27;.join([&#x27;&#x27;&#x27;&#x27;&#x27;&#x27;&#x27;]))</span></span><br><span class="line"></span><br><span class="line">        self.yslist.append(self.num.get())</span><br><span class="line">        print(self.yslist)</span><br><span class="line">        <span class="comment"># 计算结果</span></span><br><span class="line">        self.cal_res()</span><br><span class="line">        <span class="comment"># 将下一个字符添加到列表中</span></span><br><span class="line">        <span class="keyword">if</span> ysflag == <span class="string">&#x27;=&#x27;</span>:</span><br><span class="line">            self.yslist.clear()</span><br><span class="line">        <span class="comment"># 如果按的是符号</span></span><br><span class="line">        <span class="keyword">elif</span> ysflag == <span class="string">&#x27;clear&#x27;</span>:</span><br><span class="line">            self.yslist.clear()</span><br><span class="line">            self.num.<span class="built_in">set</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.yslist.append(ysflag)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 结果运算</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">cal_res</span>(<span class="params">self</span>):</span></span><br><span class="line">        res = <span class="built_in">eval</span>(<span class="string">&#x27;&#x27;</span>.join(self.yslist))</span><br><span class="line">        <span class="comment"># print(res)</span></span><br><span class="line">        self.num.<span class="built_in">set</span>(res)</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 按钮摆放方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">button_put</span>(<span class="params">self,contain,com_func, x, y</span>):</span></span><br><span class="line">        btn = tkinter.Button(self.root, text=contain, command=<span class="keyword">lambda</span>: com_func(contain))</span><br><span class="line">        btn.place(relx = (self.but_chang * x ) / self.win_chang, rely = (self.but_kuan * y) / self.win_chang, relwidth = (self.but_chang) / self.win_chang, relheight = (self.but_kuan) / self.win_chang)</span><br><span class="line">    <span class="comment"># 整体执行逻辑</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run_logic</span>(<span class="params">self</span>):</span></span><br><span class="line"></span><br><span class="line">        self.root = tkinter.Tk()</span><br><span class="line">        self.root.title(<span class="string">&#x27;最强计算器&#x27;</span>)</span><br><span class="line">        self.root.minsize(self.win_chang, self.win_kuan)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 计算器显示内容应该用字符串显示</span></span><br><span class="line"></span><br><span class="line">        self.num = tkinter.StringVar()</span><br><span class="line">        self.num.<span class="built_in">set</span>(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 创建label显示</span></span><br><span class="line">        label = tkinter.Label(self.root, textvariable = self.num, bg=<span class="string">&#x27;white&#x27;</span>, font=(<span class="string">&#x27;黑体&#x27;</span>, <span class="number">30</span>), anchor=<span class="string">&#x27;e&#x27;</span>)</span><br><span class="line">        label.place(relx=<span class="number">1</span>/<span class="number">40</span>, rely=<span class="number">1</span>/<span class="number">50</span>, relwidth=<span class="number">38</span>/<span class="number">40</span>, relheight=<span class="number">4</span>/<span class="number">30</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">10</span>):</span><br><span class="line">            self.button_put(<span class="built_in">str</span>(i), self.press_num, x=(i + <span class="number">2</span>) % <span class="number">3</span>, y=<span class="number">4</span> - (i // <span class="number">3.1</span>))</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 运算符按钮参数列表</span></span><br><span class="line">        sym_list = [</span><br><span class="line">            [<span class="string">&#x27;0&#x27;</span>,    self.press_num,<span class="number">1</span>,<span class="number">5</span>],</span><br><span class="line">            [<span class="string">&#x27;.&#x27;</span>,    self.press_num,<span class="number">2</span>,<span class="number">5</span>],</span><br><span class="line">            [<span class="string">&#x27;=&#x27;</span>,    self.press_sym,<span class="number">3</span>,<span class="number">5</span>],</span><br><span class="line">            [<span class="string">&#x27;+&#x27;</span>,    self.press_sym,<span class="number">3</span>,<span class="number">4</span>],</span><br><span class="line">            [<span class="string">&#x27;-&#x27;</span>,    self.press_sym,<span class="number">3</span>,<span class="number">3</span>],</span><br><span class="line">            [<span class="string">&#x27;*&#x27;</span>,    self.press_sym,<span class="number">3</span>,<span class="number">2</span>],</span><br><span class="line">            [<span class="string">&#x27;/&#x27;</span>,    self.press_sym,<span class="number">3</span>,<span class="number">1</span>],</span><br><span class="line">            [<span class="string">&#x27;clear&#x27;</span>,self.press_sym,<span class="number">0</span>,<span class="number">5</span>],</span><br><span class="line">            [<span class="string">&#x27;**&#x27;</span>,self.press_sym,<span class="number">2</span>,<span class="number">1</span>],</span><br><span class="line">            [<span class="string">&#x27;//&#x27;</span>,self.press_sym,<span class="number">1</span>,<span class="number">1</span>],</span><br><span class="line">        ]</span><br><span class="line">            </span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> sym_list:</span><br><span class="line">            <span class="comment"># 数字0</span></span><br><span class="line">            self.button_put(*i)</span><br><span class="line">            <span class="comment"># *加上列表 打散参数,传递给形参,类似于收地参数似的</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 加入主消息循环</span></span><br><span class="line">        self.root.mainloop()</span><br><span class="line">        <span class="comment"># 注意这行代码需要放在最后,否则可能会影响前面的变量的初始化,或程序的正常运行</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 实例化对象</span></span><br><span class="line">my_cal = Calculation()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> tkinter </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>压缩软件</title>
      <link href="python/GUI/tkinter/tkinter-zip/"/>
      <url>python/GUI/tkinter/tkinter-zip/</url>
      
        <content type="html"><![CDATA[<h3 id="控制台版本-未加入图形化界面"><a href="#控制台版本-未加入图形化界面" class="headerlink" title="控制台版本,未加入图形化界面"></a>控制台版本,未加入图形化界面</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by xiaoming</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;仅仅实现压缩功能,暂时不用图形化界面开发&gt;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> zipfile</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Zip_file</span>:</span></span><br><span class="line">    <span class="comment"># 成员属性</span></span><br><span class="line">    file_list = []</span><br><span class="line">    <span class="comment"># depress_list = []</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 成员方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 调用主方法</span></span><br><span class="line">        self.main()</span><br><span class="line">    <span class="comment"># 添加文件</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">add_file</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(<span class="string">&#x27;添加文件&#x27;</span>)</span><br><span class="line">        ori_path = <span class="built_in">input</span>(<span class="string">&#x27;请输入要压缩的文件路径&#x27;</span>)</span><br><span class="line">        self.file_list.append(ori_path)</span><br><span class="line">        print(<span class="string">&#x27;添加文件成功!列表如下:&#x27;</span>)</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> self.file_list:</span><br><span class="line">            print(i)</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 压缩文件</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">press_file</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(<span class="string">&#x27;压缩文件&#x27;</span>)</span><br><span class="line">        <span class="comment"># 目标</span></span><br><span class="line">        des_path = <span class="built_in">input</span>(<span class="string">&#x27;请输入目标路径&#x27;</span>)</span><br><span class="line">        zp = zipfile.ZipFile(des_path, <span class="string">&#x27;w&#x27;</span>,zipfile.ZIP_DEFLATED)</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> self.file_list:</span><br><span class="line">            zp.write(i,self.get_file_name(i))</span><br><span class="line">        print(<span class="string">&#x27;压缩文件成功&#x27;</span>)</span><br><span class="line">        <span class="comment"># print(&#x27;目标文件位置为:&#x27;)</span></span><br><span class="line">        <span class="comment"># print(res)</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 解压文件</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">depress_file</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(<span class="string">&#x27;解压文件&#x27;</span>)</span><br><span class="line">        src_path = <span class="built_in">input</span>(<span class="string">&#x27;请输入要解压的文件路径&#x27;</span>)</span><br><span class="line">        <span class="comment"># self.depress_list.append(src_path)</span></span><br><span class="line">        <span class="comment"># zipfile.ZipFile.extractall(src_path)</span></span><br><span class="line">        <span class="comment"># print(&#x27;解压文件到当前文件夹&#x27;)</span></span><br><span class="line">        des_path = <span class="built_in">input</span>(<span class="string">&#x27;请输入目标文件路径&#x27;</span>)</span><br><span class="line">        zp = zipfile.ZipFile(src_path,<span class="string">&#x27;r&#x27;</span>)</span><br><span class="line">        <span class="keyword">for</span> file <span class="keyword">in</span> zp.namelist():</span><br><span class="line">            zp.extract(file, self.get_file_name(file))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&#x27;解压缩成功&#x27;</span>)</span><br><span class="line">        zp.close()</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 用于获取路径后面的文件名称</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_file_name</span>(<span class="params">self,path</span>):</span></span><br><span class="line">        <span class="keyword">import</span> os</span><br><span class="line">        new_name = os.path.split(path)[<span class="number">1</span>]</span><br><span class="line">        <span class="keyword">return</span> new_name</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 定义逻辑主函数,用于模拟tkinter的操作,简化程序先</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">main</span>(<span class="params">self</span>):</span></span><br><span class="line">        info = <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">                1.添加文件</span></span><br><span class="line"><span class="string">                2.压缩文件</span></span><br><span class="line"><span class="string">                3.解压文件</span></span><br><span class="line"><span class="string">                0.退出</span></span><br><span class="line"><span class="string">                &#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">        print(info)</span><br><span class="line">        cho = <span class="built_in">input</span>(<span class="string">&#x27;请选择:&#x27;</span>)</span><br><span class="line">        <span class="comment"># print(&#x27;控制逻辑部分&#x27;)</span></span><br><span class="line">        <span class="keyword">if</span> cho == <span class="string">&#x27;1&#x27;</span>:</span><br><span class="line">            self.add_file()</span><br><span class="line">            <span class="comment"># self.add_file()</span></span><br><span class="line">            self.main()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&#x27;2&#x27;</span>:</span><br><span class="line">            self.press_file()</span><br><span class="line">            self.main()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&#x27;3&#x27;</span>:</span><br><span class="line">            self.depress_file()</span><br><span class="line">            self.main()</span><br><span class="line">        <span class="keyword">elif</span> cho == <span class="string">&#x27;0&#x27;</span>:</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&#x27;输入有误!重新输入&#x27;</span>)</span><br><span class="line">            self.main()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 实例化对象</span></span><br><span class="line">z = Zip_file()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="图形化开发版本"><a href="#图形化开发版本" class="headerlink" title="图形化开发版本"></a>图形化开发版本</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by xiaoming</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;tkinter图形化界面开发,实现压缩功能&gt;</span></span><br><span class="line"><span class="comment"># 本次加入了提示弹窗的功能</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在添加文件的时候,不能追加添加,添加多次的结果就是最后一次选中的文件(以完善)</span></span><br><span class="line"><span class="comment"># 类的使用,在类的成员方法中可以使用类中的成员属性,而不需要考虑变量的作用域的问题</span></span><br><span class="line"><span class="comment"># 只需要在变量前面加上一个self的对象本身调用</span></span><br><span class="line"><span class="comment"># 进行实例化类的同时,执行了__init__ 初始化方法</span></span><br><span class="line"><span class="comment"># 并在__init__方法中 调用控制函数 进行其他方法的执行,并加入了tkinter的图形化操作</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># TODO 1.重名文件覆盖问题(加yesno框)</span></span><br><span class="line"><span class="comment"># TODO 2.自动清空文件列表(已完成)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入 压缩模块</span></span><br><span class="line"><span class="keyword">import</span> zipfile</span><br><span class="line"><span class="comment"># 导入 系统模块,用于判断文件是否存在</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="comment"># 导入 tkinter模块 ,图形化界面</span></span><br><span class="line"><span class="keyword">import</span> tkinter</span><br><span class="line"><span class="keyword">import</span> tkinter.filedialog</span><br><span class="line"><span class="keyword">import</span> tkinter.messagebox</span><br><span class="line"><span class="keyword">import</span> tkinter.simpledialog</span><br><span class="line"></span><br><span class="line"><span class="comment"># 定义压缩类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Zip_file</span>:</span></span><br><span class="line">    <span class="comment"># 成员属性</span></span><br><span class="line">    file_list = []</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 成员方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 调用逻辑处理</span></span><br><span class="line">        self.logic()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 控制窗口逻辑</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">logic</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 创建窗口对象</span></span><br><span class="line">        root = tkinter.Tk()</span><br><span class="line">        root.minsize(<span class="number">300</span>, <span class="number">300</span>)</span><br><span class="line">        </span><br><span class="line">        btn_add = tkinter.Button(root, text=<span class="string">&#x27;添加文件到列表&#x27;</span>, command=self.add_file)</span><br><span class="line">        btn_add.grid(row=<span class="number">1</span>, column=<span class="number">0</span>)</span><br><span class="line">        btn_ys = tkinter.Button(root, text=<span class="string">&#x27;开始压缩&#x27;</span>, command=self.press_file)</span><br><span class="line">        btn_ys.grid(row=<span class="number">1</span>, column=<span class="number">1</span>)</span><br><span class="line">        btn_jy = tkinter.Button(root, text=<span class="string">&#x27;开始解压&#x27;</span>, command=self.depress_file)</span><br><span class="line">        btn_jy.grid(row=<span class="number">1</span>, column=<span class="number">2</span>)</span><br><span class="line">        btn_jy = tkinter.Button(root, text=<span class="string">&#x27;清空当前文件列表&#x27;</span>, command=self.clear_file)</span><br><span class="line">        btn_jy.grid(row=<span class="number">3</span>, column=<span class="number">0</span>, columnspan = <span class="number">3</span>)</span><br><span class="line"></span><br><span class="line">        self.val = tkinter.StringVar()</span><br><span class="line">        self.val.<span class="built_in">set</span>(<span class="string">&#x27;                 暂无文件信息                 &#x27;</span>)</span><br><span class="line">        label1 = tkinter.Label(root, textvariable=self.val, bg=<span class="string">&#x27;pink&#x27;</span>)</span><br><span class="line">        label1.grid(row=<span class="number">2</span>, column=<span class="number">0</span>, columnspan=<span class="number">3</span>)</span><br><span class="line"></span><br><span class="line">        self.val2 = tkinter.StringVar()</span><br><span class="line">        self.val2.<span class="built_in">set</span>(<span class="string">&#x27;    压缩或解压前请先添加文件到列表    &#x27;</span>)</span><br><span class="line">        label2 = tkinter.Label(root, textvariable=self.val2, bg=<span class="string">&#x27;yellow&#x27;</span>)</span><br><span class="line">        label2.grid(row=<span class="number">0</span>, column=<span class="number">0</span>, columnspan = <span class="number">3</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 加入主消息循环</span></span><br><span class="line">        root.mainloop()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 清空文件列表</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">clear_file</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.file_list.clear()</span><br><span class="line">        self.val.<span class="built_in">set</span>(<span class="string">&#x27;暂无文件信息!&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 添加文件</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">add_file</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(<span class="string">&#x27;添加文件&#x27;</span>)</span><br><span class="line">        <span class="comment"># 获得需要添加的文件路径列表</span></span><br><span class="line">        file_name_temp = <span class="built_in">list</span>(tkinter.filedialog.askopenfilenames(title=<span class="string">&#x27;请选择要压缩的文件&#x27;</span>))</span><br><span class="line">        <span class="comment"># 判断用户取消没</span></span><br><span class="line">        <span class="keyword">if</span> file_name_temp:</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        self.file_list += file_name_temp</span><br><span class="line">        file_set = <span class="built_in">set</span>(self.file_list)</span><br><span class="line">        file_set_list = <span class="built_in">list</span>(file_set)</span><br><span class="line">        <span class="comment"># ori_path = input(&#x27;请输入要压缩的文件路径&#x27;)</span></span><br><span class="line">        <span class="comment"># self.file_list.append(ori_path)</span></span><br><span class="line">        tkinter.messagebox.showinfo(<span class="string">&#x27;提示&#x27;</span>, <span class="string">&#x27;文件添加成功,可在列表中查看&#x27;</span>)</span><br><span class="line">        <span class="comment"># print(&#x27;添加文件成功!文件列表如下:&#x27;)</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> file_set:</span><br><span class="line">            print(i)</span><br><span class="line"></span><br><span class="line">        self.val.<span class="built_in">set</span>(<span class="string">&#x27;\n&#x27;</span>.join(file_set_list))</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 压缩文件</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">press_file</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># tkinter.simpledialog</span></span><br><span class="line">        print(<span class="string">&#x27;压缩文件&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 目标</span></span><br><span class="line">        <span class="comment"># 弹出对话框返回压缩路径</span></span><br><span class="line">        self.des_path = tkinter.filedialog.askdirectory(title=<span class="string">&#x27;请选择压缩包保存的路径&#x27;</span>)</span><br><span class="line">        <span class="comment"># 如果用户取消选择</span></span><br><span class="line">        <span class="keyword">if</span> self.des_path:</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        print(<span class="string">&#x27;压缩的路径是:&#x27;</span>)</span><br><span class="line">        print(self.des_path)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 提示输入压缩文件名</span></span><br><span class="line">        file_name = tkinter.simpledialog.askstring(\</span><br><span class="line">            title=<span class="string">&#x27;获取信息&#x27;</span>, prompt=<span class="string">&#x27;给你的新压缩包起个名字吧&#x27;</span>, initialvalue=<span class="string">&#x27;demo&#x27;</span>)</span><br><span class="line">        file_name = file_name + <span class="string">&#x27;.zip&#x27;</span></span><br><span class="line">        print(file_name)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 判断文件存在否</span></span><br><span class="line">        <span class="keyword">if</span> os.path.exists(self.des_path+<span class="string">&#x27;/&#x27;</span>+file_name):</span><br><span class="line">            <span class="comment"># 文件已经存在</span></span><br><span class="line">            <span class="comment"># 询问用户</span></span><br><span class="line"></span><br><span class="line">            result = tkinter.messagebox.askquestion(title=<span class="string">&#x27;系统提醒&#x27;</span>, message=<span class="string">&#x27;文件已存在,是否替换原文件&#x27;</span>)</span><br><span class="line">            print(result)</span><br><span class="line">            <span class="keyword">if</span> result == <span class="string">&#x27;yes&#x27;</span>:</span><br><span class="line">                print(<span class="string">&#x27;用户选择的是&#x27;</span>)</span><br><span class="line">                <span class="comment"># 返回 ,重新选择路径</span></span><br><span class="line">                <span class="comment"># 警告用户错误</span></span><br><span class="line">                <span class="keyword">pass</span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                tkinter.messagebox.showwarning(title=<span class="string">&#x27;警告&#x27;</span>, message=<span class="string">&#x27;请重新选择目录&#x27;</span>)</span><br><span class="line">                self.press_file()</span><br><span class="line">                <span class="comment"># print(result)</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="comment"># 路径不存在,正常执行</span></span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        zp = zipfile.ZipFile(self.des_path+<span class="string">&#x27;/&#x27;</span>+file_name, <span class="string">&#x27;w&#x27;</span>,zipfile.ZIP_DEFLATED)</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">set</span>(self.file_list):</span><br><span class="line">            zp.write(i,self.get_file_name(i)[<span class="number">1</span>])</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            tkinter.messagebox.showinfo(\</span><br><span class="line">                <span class="string">&#x27;提示&#x27;</span>, <span class="string">&#x27;压缩文件%s保存成功&#x27;</span> % self.des_path+<span class="string">&#x27;/&#x27;</span>+file_name)</span><br><span class="line">        <span class="comment"># print(&#x27;压缩文件成功&#x27;)</span></span><br><span class="line">        zp.close()</span><br><span class="line">        self.clear_file()</span><br><span class="line"></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 解压文件</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">depress_file</span>(<span class="params">self</span>):</span></span><br><span class="line">        print(<span class="string">&#x27;解压文件&#x27;</span>)</span><br><span class="line">        <span class="comment"># # 方式1</span></span><br><span class="line">        <span class="comment"># src_path_list = tkinter.filedialog.askopenfilenames(title=&#x27;请选择解压文件路径&#x27;)</span></span><br><span class="line">        <span class="comment">#</span></span><br><span class="line">        <span class="comment"># # 判断用户取消没</span></span><br><span class="line">        <span class="comment"># if src_path_list:</span></span><br><span class="line">        <span class="comment">#     pass</span></span><br><span class="line">        <span class="comment"># else:</span></span><br><span class="line">        <span class="comment">#     return</span></span><br><span class="line">        <span class="comment"># 方式2</span></span><br><span class="line">        src_path_list = <span class="built_in">set</span>(self.file_list)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 选择保存位置</span></span><br><span class="line">        des_path = tkinter.filedialog.askdirectory(title=<span class="string">&#x27;请选择解压后文件保存的路径&#x27;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 判断用户取消没</span></span><br><span class="line">        <span class="keyword">if</span> des_path:</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># des_path = self.get_file_name(self.src_path)[0]</span></span><br><span class="line">        <span class="comment"># 这里测试出一个bug</span></span><br><span class="line">        <span class="comment"># 如果用户没有添加文件,而直接点击了解压文件按钮</span></span><br><span class="line">        <span class="comment"># TODO 应该提供一个提示信息</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> src_path <span class="keyword">in</span> src_path_list:</span><br><span class="line">            <span class="comment"># des_path = self.get_file_name(src_path)[0]</span></span><br><span class="line">            zp = zipfile.ZipFile(src_path,<span class="string">&#x27;r&#x27;</span>)</span><br><span class="line">            <span class="keyword">for</span> file <span class="keyword">in</span> zp.namelist():</span><br><span class="line">                print(file)</span><br><span class="line">                zp.extract(file,des_path)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                tkinter.messagebox.showinfo(<span class="string">&#x27;提示&#x27;</span>, <span class="string">&#x27;解压缩文件%s成功&#x27;</span> % src_path)</span><br><span class="line">                <span class="comment"># print()</span></span><br><span class="line">            zp.close()</span><br><span class="line">        self.clear_file()</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 用于获取路径后面的文件名称</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_file_name</span>(<span class="params">self,path</span>):</span></span><br><span class="line">        <span class="keyword">import</span> os</span><br><span class="line">        new_name = os.path.split(path)</span><br><span class="line">        <span class="keyword">return</span> new_name</span><br><span class="line"></span><br><span class="line"><span class="comment"># 实例化对象</span></span><br><span class="line">z = Zip_file()</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> tkinter </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Bootstrap 响应式设计</title>
      <link href="front/bootstrap/bootstrap-Responsive.md/"/>
      <url>front/bootstrap/bootstrap-Responsive.md/</url>
      
        <content type="html"><![CDATA[<h3 id="什么是响应式-Web-设计"><a href="#什么是响应式-Web-设计" class="headerlink" title="什么是响应式 Web 设计"></a>什么是响应式 Web 设计</h3><p>响应式 Web 设计是一个让用户通过各种尺寸的设备浏览网站获得良好的视觉效果的方法。</p><p>例如，您先在计算机显示器上浏览一个网站，然后在智能手机上浏览，智能手机的屏幕尺寸远小于计算机显示器，但是你却没有感觉到任何差别，两者的用户体验几乎一样，这说明这个网站在响应式设计方面做得很好。</p><h3 id="响应式-Web-设计工作原理"><a href="#响应式-Web-设计工作原理" class="headerlink" title="响应式 Web 设计工作原理"></a>响应式 Web 设计工作原理</h3><p>为了应用响应式 Web 设计，您需要创建一个包含适应各种设备尺寸样式的 CSS。</p><p>一旦页面在特定的设备上加载，该页面上使用了各种字体和 Web 开发技术，比如媒体查询（Media Queries），此时，会先检测设备的视口大小，然后加载特定于设备的样式。</p><h3 id="为了让布局更具响应性，Bootstrap-做了三件事情："><a href="#为了让布局更具响应性，Bootstrap-做了三件事情：" class="headerlink" title="为了让布局更具响应性，Bootstrap 做了三件事情："></a>为了让布局更具响应性，Bootstrap 做了三件事情：</h3><ol><li><p>修改了网格中列的宽度。</p></li><li><p>只要有需要，它就使用堆栈元素，而不是浮动元素。如果您还不清楚什么是堆栈元素，下面来自 w3.org 的表单可能会提供一些帮助：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">根元素（html）形成了堆栈上下文的根，其他堆栈上下文通过任意定位的元素生成（包括相对定位元素，有一个 &#39;z-index&#39; 的计算值，而不是 &#39;auto&#39;）。堆栈上下文相对与包含的块不是必需的。</span><br></pre></td></tr></table></figure></li><li><p>要正确地渲染标题和文字它们的尺寸。</p></li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> Bootstrap </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>前端框架之react介绍</title>
      <link href="front/react/react-intorduce/"/>
      <url>front/react/react-intorduce/</url>
      
        <content type="html"><![CDATA[<h3 id="声明式"><a href="#声明式" class="headerlink" title="声明式"></a>声明式</h3><p>React 可以非常轻松地创建用户交互界面。为你应用的每一个状态设计简洁的视图，在数据改变时 React 也可以高效地更新渲染界面。</p><p>以声明式编写UI，可以让你的代码更加可靠，且方便调试。</p><h3 id="组件化"><a href="#组件化" class="headerlink" title="组件化"></a>组件化</h3><p>创建好拥有各自状态的组件，再由组件构成更加复杂的界面。</p><p>无需再用模版代码，通过使用JavaScript编写的组件你可以更好地传递数据，将应用状态和DOM拆分开来。</p><h3 id="一次学习，随处编写"><a href="#一次学习，随处编写" class="headerlink" title="一次学习，随处编写"></a>一次学习，随处编写</h3><p>无论你现在正在使用什么技术栈，你都可以随时引入 React 开发新特性。</p><p>React 也可以用作开发原生应用的框架 React Native.</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>前端框架之webpack介绍</title>
      <link href="front/webpack/webpack-intorduce/"/>
      <url>front/webpack/webpack-intorduce/</url>
      
        <content type="html"><![CDATA[<h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>本质上，webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时，它会递归地构建一个依赖关系图(dependency graph)，其中包含应用程序需要的每个模块，然后将所有这些模块打包成一个或多个 bundle。  </p><h3 id="模块-modules"><a href="#模块-modules" class="headerlink" title="模块(modules)"></a>模块(modules)</h3><p>在模块化编程中，开发者将程序分解成离散功能块<code>(discrete chunks of functionality)</code>，并称之为模块。  </p><p>每个模块具有比完整程序更小的接触面，使得校验、调试、测试轻而易举。 精心编写的模块提供了可靠的抽象和封装界限，使得应用程序中每个模块都具有条理清楚的设计和明确的目的。  </p><p>Node.js 从最一开始就支持模块化编程。然而，在 web，模块化的支持正缓慢到来。在 web 存在多种支持 JavaScript 模块化的工具，这些工具各有优势和限制。webpack 基于从这些系统获得的经验教训，并将模块的概念应用于项目中的任何文件。  </p><h3 id="什么是-webpack-模块"><a href="#什么是-webpack-模块" class="headerlink" title="什么是 webpack 模块"></a>什么是 webpack 模块</h3><p>对比 Node.js 模块，webpack 模块能够以各种方式表达它们的依赖关系，几个例子如下：  </p><p>ES2015 import 语句<br>CommonJS require() 语句<br>AMD define 和 require 语句<br>css/sass/less 文件中的 @import 语句。<br>样式<code>(url(...))</code>或 HTML 文件<code>(&lt;img src=...&gt;)</code>中的图片链接<code>(image url)</code>  </p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>前端相关优质项目推荐</title>
      <link href="front/front-pro/"/>
      <url>front/front-pro/</url>
      
        <content type="html"><![CDATA[<div class="row"><pre><code>    &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;http://www.youzhan.org/&quot; title=&quot;Bootstrap 优站精选&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;youzhan-tile&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/expo.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/expo.png&quot; alt=&quot;Bootstrap 优站精选&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;http://www.youzhan.org/&quot; title=&quot;Bootstrap 优站精选&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;youzhan-tile&#39;])&quot;&gt;优站精选&lt;br&gt;&lt;small&gt; Bootstrap 网站实例&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Bootstrap 优站精选频道收集了众多基于 Bootstrap 构建、设计精美的、有创意的网站。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.webpackjs.com/&quot; title=&quot;Webpack 是前端资源模块化管理和打包工具&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;webpack&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/webpack.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/webpack.png&quot; alt=&quot;Webpack 是前端资源模块化管理和打包工具&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.webpackjs.com/&quot; title=&quot;Webpack 是前端资源模块化管理和打包工具&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;webpack&#39;])&quot;&gt;Webpack&lt;br&gt;&lt;small&gt;是前端资源模块化管理和打包工具&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.reactjscn.com/&quot; title=&quot;React - 用于构建用户界面的 JavaScript 框架&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;react&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/react.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/react.png&quot; alt=&quot;React - 用于构建用户界面的 JavaScript 框架&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.reactjscn.com/&quot; title=&quot;React - 用于构建用户界面的 JavaScript 框架&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;react&#39;])&quot;&gt;React&lt;br&gt;&lt;small&gt;用于构建用户界面的 JavaScript 框架&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;React 起源于 Facebook 的内部项目，是一个用于构建用户界面的 JavaScript 库。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://typescript.bootcss.com/&quot; title=&quot;TypeScript 中文手册&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;typescript&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/typescript.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/typescript.png&quot; alt=&quot;TypeScript 中文手册&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://typescript.bootcss.com/&quot; title=&quot;TypeScript 中文手册&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;typescript&#39;])&quot;&gt;TypeScript &lt;br&gt;&lt;small&gt;中文手册&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;TypeScript 是由微软开源的编程语言。它是 JavaScript 的一个超集，而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.jquery123.com/&quot; title=&quot;jQuery API 中文文档/手册&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;jQueryAPI中文手册&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/jqueryapi.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/jqueryapi.png&quot; alt=&quot;jQuery API 中文文档/手册&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.jquery123.com/&quot; title=&quot;jQuery API 中文文档/手册&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;jQueryAPI中文手册&#39;])&quot;&gt;jQuery API &lt;br&gt;&lt;small&gt;中文手册&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;根据最新的 jQuery 1.11.x 和 2.1.x 版本翻译的 jQuery API 中文文档/手册。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.nextjs.cn/&quot; title=&quot;Next.js 是一个轻量级的 React 服务端渲染应用框架。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;nextjs&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/nextjs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/nextjs.png&quot; alt=&quot;Next.js 是一个轻量级的 React 服务端渲染应用框架。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.nextjs.cn/&quot; title=&quot;Next.js 是一个轻量级的 React 服务端渲染应用框架。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;nextjs&#39;])&quot;&gt;Next.js&lt;br&gt;&lt;small&gt;中文文档&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Next.js 是一个轻量级的 React 服务端渲染应用框架。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.babeljs.cn&quot; title=&quot;Babel 是一个 JavaScript 编译器。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;babel&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/babeljs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/babeljs.png&quot; alt=&quot;Babel 是一个 JavaScript 编译器。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.babeljs.cn&quot; title=&quot;Babel 是一个 JavaScript 编译器。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;babel&#39;])&quot;&gt;Babel &lt;br&gt;&lt;small&gt;是一个 JavaScript 编译器。&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Babel 是一个 JavaScript 编译器。Babel 通过语法转换器支持最新版本的 JavaScript 语法。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.nodeapp.cn/&quot; title=&quot;Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型，使其轻量又高效。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;node&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/nodejs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/nodejs.png&quot; alt=&quot;Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型，使其轻量又高效。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.nodeapp.cn/&quot; title=&quot;Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型，使其轻量又高效。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;node&#39;])&quot;&gt;Node.js&lt;br&gt;&lt;small&gt;中文文档 / 手册&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型，使其轻量又高效。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://yarn.bootcss.com/&quot; title=&quot;Yarn 是一个快速、可靠、安全的依赖管理工具。是 NPM 的替代品。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;Yarn&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/yarn.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/yarn.png&quot; alt=&quot;Yarn 是一个快速、可靠、安全的依赖管理工具。是 NPM 的替代品。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://yarn.bootcss.com/&quot; title=&quot;Yarn 是一个快速、可靠、安全的依赖管理工具。是 NPM 的替代品。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;Yarn&#39;])&quot;&gt;Yarn &lt;br&gt;&lt;small&gt;中文手册&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Yarn 是一个快速、可靠、安全的依赖管理工具。是 NPM 的替代品。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.npmjs.cn/&quot; title=&quot;NPM 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;npm&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/npm.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/npm.png&quot; alt=&quot;NPM 中文文档&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.npmjs.cn/&quot; title=&quot;NPM 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;npm&#39;])&quot;&gt;NPM &lt;br&gt;&lt;small&gt;中文文档&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;NPM（node package manager）是 Node.js 世界的包管理器。NPM 可以让 JavaScript 开发者在共享代码、复用代码以及更新共享的代码上更加方便。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://vuejs.bootcss.com/&quot; title=&quot;Vue.js - 渐进式 JavaScript 框架&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;vuejs&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/vuejs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/vuejs.png&quot; alt=&quot;Vue.js - 渐进式 JavaScript 框架&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://vuejs.bootcss.com/&quot; title=&quot;Vue.js - 渐进式 JavaScript 框架&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;vuejs&#39;])&quot;&gt;Vue.js&lt;br&gt;&lt;small&gt; 中文文档。&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Vue.js - 是一套构建用户界面的渐进式框架。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.sveltejs.cn/&quot; title=&quot;Svelte&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;svelte&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/svelte.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/svelte.png&quot; alt=&quot;Svelte&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.sveltejs.cn/&quot; title=&quot;Svelte&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;svelte&#39;])&quot;&gt;Svelte&lt;br&gt;&lt;small&gt;中文网&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Svelte 是构建 Web 应用程序的一种新方法。Svelte 是一个编译器，它将声明性组件转换成高效的 JavaScript 代码，并像做外科手术一样细粒度地更新 DOM。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://browsersync.bootcss.com/&quot; title=&quot;Browsersync 浏览器同步测试工具&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;browsersync&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/browsersync.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/browsersync.png&quot; alt=&quot;Browsersync 浏览器同步测试工具&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://browsersync.bootcss.com/&quot; title=&quot;Browsersync 浏览器同步测试工具&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;browsersync&#39;])&quot;&gt;Browsersync&lt;br&gt;&lt;small&gt;浏览器同步测试工具&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Browsersync 浏览器同步测试工具，很容易与 Web 平台、构建工具和其他 Node.js 项目集成，替代了大量重复测试劳动。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.parceljs.cn/&quot; title=&quot;Parcel - 极速、零配置的 web 应用打包工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;parcel&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/parcel.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/parcel.png&quot; alt=&quot;Parcel - 极速、零配置的 web 应用打包工具。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.parceljs.cn/&quot; title=&quot;Parcel - 极速、零配置的 web 应用打包工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;parcel&#39;])&quot;&gt;Parcel &lt;br&gt;&lt;small&gt;中文文档&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Parcel - 极速、零配置的 web 应用打包工具。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.lodashjs.com/&quot; title=&quot;Lodash 是最流行的 JavaScript 工具库。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;lodash&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/lodash.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/lodash.png&quot; alt=&quot;Lodash 是最流行的 JavaScript 工具库。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.lodashjs.com/&quot; title=&quot;Lodash 是最流行的 JavaScript 工具库。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;lodash&#39;])&quot;&gt;Lodash&lt;br&gt;&lt;small&gt;JavaScript 工具库&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Lodash 是一个具有一致接口、模块化、高性能等特性的 JavaScript 工具库。比相同功能的 Underscore.js 使用更广泛。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://progit.bootcss.com/&quot; title=&quot;Pro Git 中文版（第二版）让你从 Git 初学者成为 Git 专家&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;progit&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/progit.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/progit.png&quot; alt=&quot;Pro Git 中文版（第二版）让你从 Git 初学者成为 Git 专家&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://progit.bootcss.com/&quot; title=&quot;Pro Git 中文版（第二版）让你从 Git 初学者成为 Git 专家&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;progit&#39;])&quot;&gt;Pro Git &lt;br&gt;&lt;small&gt;Git 入门到专家指南&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Pro Git 中文版（第二版）是一本详细的 Git 指南，主要介绍了 Git 的使用基础和原理，让你从 Git 初学者成为 Git 专家。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://codeguide.bootcss.com&quot; title=&quot;Bootstrap 编码规范&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;codeguide&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/codeguide.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/codeguide.png&quot; alt=&quot;Bootstrap 编码规范&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://codeguide.bootcss.com&quot; title=&quot;Bootstrap 编码规范&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;codeguide&#39;])&quot;&gt;Bootstrap 编码规范&lt;br&gt;&lt;small&gt;by @mdo&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Bootstrap 编码规范：编写灵活、稳定、高质量的 HTML 和 CSS 代码的规范。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.rollupjs.com&quot; title=&quot;rollup.js 是新一代的 JavaScript 模块打包工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;rollup&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/rollup.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/rollup.png&quot; alt=&quot;rollup.js 是新一代的 JavaScript 模块打包工具。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.rollupjs.com&quot; title=&quot;rollup.js 是新一代的 JavaScript 模块打包工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;rollup&#39;])&quot;&gt;Rollup &lt;br&gt;&lt;small&gt;新一代的 JavaScript 模块打包工具&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Rollup 是一个 JavaScript 模块打包工具，可以将小块代码编译成大块复杂的代码。Rollup 对 JavaScript 代码模块使用新的 ES6 标准化格式，如 CommonJS 和 AMD。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://preact.bootcss.com/&quot; title=&quot;Preact - 一个只有 3kB 大小的 React 替代品，拥有与 React 相同的 API、组件和虚拟 DOM。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;preact&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/preact.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/preact.png&quot; alt=&quot;Preact - 一个只有 3kB 大小的 React 替代品，拥有与 React 相同的 API、组件和虚拟 DOM。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://preact.bootcss.com/&quot; title=&quot;Preact - 一个只有 3kB 大小的 React 替代品，拥有与 React 相同的 API、组件和虚拟 DOM。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;preact&#39;])&quot;&gt;Preact&lt;br&gt;&lt;small&gt;React 轻量替代方案。&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Preact - 一个只有 3kB 大小的 React 替代品，拥有与 React 相同的 API、组件和虚拟 DOM。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/underscore/&quot; title=&quot;Underscore.js 是一个 JavaScript 工具库&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;underscore&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/underscore.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/underscore.png&quot; alt=&quot;Underscore.js 是一个 JavaScript 工具库&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/underscore/&quot; title=&quot;Underscore.js 是一个 JavaScript 工具库&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;underscore&#39;])&quot;&gt;Underscore.js&lt;br&gt;&lt;small&gt;JavaScript 工具库&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Underscore.js是一个 JavaScript 工具库，它提供了一整套函数式编程的实用功能，弥补了 jQuery 没有实现的功能，同时又是 Backbone 必不可少的部分。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.gulpjs.com.cn/&quot; title=&quot;gulp.js - 基于流的自动化构建工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;gulp&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/gulpjs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/gulpjs.png&quot; alt=&quot;gulp.js - 基于流的自动化构建工具。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.gulpjs.com.cn/&quot; title=&quot;gulp.js - 基于流的自动化构建工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;gulp&#39;])&quot;&gt;gulp.js&lt;br&gt;&lt;small&gt;基于流的自动化构建工具。&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;gulp.js - 基于流(stream)的自动化构建工具。Grunt 采用配置文件的方式执行任务，而 Gulp 一切都通过代码实现。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;http://www.gruntjs.net&quot; title=&quot;Grunt 是基于 Node.js 的项目构建工具&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;grunt&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/gruntjs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/gruntjs.png&quot; alt=&quot;Grunt 是基于 Node.js 的项目构建工具&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;http://www.gruntjs.net&quot; title=&quot;Grunt 是基于 Node.js 的项目构建工具&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;grunt&#39;])&quot;&gt;Grunt &lt;br&gt;&lt;small&gt;项目构建工具&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Grunt 是基于 Node.js 的项目构建工具。它可以自动运行你所设定的任务。Grunt 拥有数量庞大的插件，几乎任何你所要做的事情都可以用 Grunt 实现。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://cn.eslint.org/&quot; title=&quot;ESLint 是一个插件化并且可配置的 JavaScript 语法规则和代码风格的检查工具。ESLint 能够帮你轻松写出高质量的 JavaScript 代码。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;eslint&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/eslint.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/eslint.png&quot; alt=&quot;ESLint 是一个插件化并且可配置的 JavaScript 语法规则和代码风格的检查工具。ESLint 能够帮你轻松写出高质量的 JavaScript 代码。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://cn.eslint.org/&quot; title=&quot;ESLint 是一个插件化并且可配置的 JavaScript 语法规则和代码风格的检查工具。ESLint 能够帮你轻松写出高质量的 JavaScript 代码。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;eslint&#39;])&quot;&gt;ESLint &lt;br&gt;&lt;small&gt;JavaScript 代码检查工具&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;ESLint 是一个插件化并且可配置的 JavaScript 语法规则和代码风格的检查工具。ESLint 能够帮你轻松写出高质量的 JavaScript 代码。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.sasscss.com&quot; title=&quot;Sass 是一个成熟、稳定、强大的 CSS 扩展语言解析器。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;sass&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/sass.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/sass.png&quot; alt=&quot;Sass 是一个成熟、稳定、强大的 CSS 扩展语言解析器。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.sasscss.com&quot; title=&quot;Sass 是一个成熟、稳定、强大的 CSS 扩展语言解析器。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;sass&#39;])&quot;&gt;Sass &lt;br&gt;&lt;small&gt;最流行的 CSS 扩展语言解析器&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Sass 是一个成熟、稳定、强大的 CSS 扩展语言解析器。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/lesscss/&quot; title=&quot;LESS 一种动态样式语言&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;lesscss&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/lesscss.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/lesscss.png&quot; alt=&quot;LESS 一种动态样式语言&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/lesscss/&quot; title=&quot;LESS 一种动态样式语言&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;lesscss&#39;])&quot;&gt;LESS &lt;br&gt;&lt;small&gt;一种动态样式语言&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;LESS 为 CSS 赋予了动态语言的特性，如变量、继承、运算、函数。LESS 既可以在客户端上运行 (支持 IE 6+、Webkit、Firefox)，也可以借助 Node.js 或者 Rhino 在服务端运行。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://handlebars.bootcss.com&quot; title=&quot;Handlebars 模板引擎&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;handlebars&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/handlebars.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/handlebars.png&quot; alt=&quot;Handlebars 模板引擎&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://handlebars.bootcss.com&quot; title=&quot;Handlebars 模板引擎&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;handlebars&#39;])&quot;&gt;Handlebars &lt;br&gt;&lt;small&gt;一个书写高效率、语义化的模板引擎&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Handlebars 是一个书写高效率、语义化的模板引擎，与 Mustache 模板兼容。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://stylus.bootcss.com/&quot; title=&quot;Stylus -- CSS 预处理语言&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;stylus&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/stylus.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/stylus.png&quot; alt=&quot;Stylus -- CSS 预处理语言&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://stylus.bootcss.com/&quot; title=&quot;Stylus -- CSS 预处理语言&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;stylus&#39;])&quot;&gt;Stylus &lt;br&gt;&lt;small&gt;CSS 预处理语言&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Stylus - 富于表现力、健壮、功能丰富的 CSS 预处理语言。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://pug.bootcss.com/api/getting-started.html&quot; title=&quot;Pug - 健壮、灵活、功能丰富的 Node.js 模板引擎&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;pug&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/pug.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/pug.png&quot; alt=&quot;Pug - 健壮、灵活、功能丰富的 Node.js 模板引擎&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://pug.bootcss.com/api/getting-started.html&quot; title=&quot;Pug - 健壮、灵活、功能丰富的 Node.js 模板引擎&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;pug&#39;])&quot;&gt;Pug &lt;br&gt;&lt;small&gt;Node.js 模板引擎&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Pug 是一款健壮、灵活、功能丰富的模板引擎，专门为 Node.js 平台开发。Pug 是由 Jade 改名而来。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://liquid.bootcss.com/&quot; title=&quot;Liquid - Jekyll 的模板语言。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;liquid&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/liquid.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/liquid.png&quot; alt=&quot;Liquid - Jekyll 的模板语言。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://liquid.bootcss.com/&quot; title=&quot;Liquid - Jekyll 的模板语言。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;liquid&#39;])&quot;&gt;Liquid&lt;br&gt;&lt;small&gt;Jekyll 的模板语言。&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Liquid - 最流行的模板语言。Jekyll、Github Pages 都在用。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://zeptojs.bootcss.com/&quot; title=&quot;Zepto.js 是一个轻量级、兼容 jQuery 的 JavaScript 工具库&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;zepto.js&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/zeptojs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/zeptojs.png&quot; alt=&quot;Zepto.js 是一个轻量级、兼容 jQuery 的 JavaScript 工具库&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://zeptojs.bootcss.com/&quot; title=&quot;Zepto.js 是一个轻量级、兼容 jQuery 的 JavaScript 工具库&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;zepto.js&#39;])&quot;&gt;Zepto.js &lt;br&gt;&lt;small&gt;JavaScript 工具库&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Zepto.js 是一个轻量级、兼容 jQuery 的 JavaScript 工具库。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://ejs.bootcss.com/&quot; title=&quot;EJS 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;ejs&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/ejs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/ejs.png&quot; alt=&quot;EJS 中文文档&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://ejs.bootcss.com/&quot; title=&quot;EJS 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;ejs&#39;])&quot;&gt;EJS &lt;br&gt;&lt;small&gt;中文文档&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;EJS 是一套简单的模板语言，帮你利用普通的 JavaScript 代码生成 HTML 页面。EJS 没有再造一套迭代和控制流语法，有的只是普通的 JavaScript 代码而已。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.tailwindcss.cn/&quot; title=&quot;Tailwind CSS 中文网 / 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;tailwindcss&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/tailwindcss.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/tailwindcss.png&quot; alt=&quot;Tailwind CSS 中文网 / 中文文档&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.tailwindcss.cn/&quot; title=&quot;Tailwind CSS 中文网 / 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;tailwindcss&#39;])&quot;&gt;Tailwind CSS &lt;br&gt;&lt;small&gt;中文文档&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Tailwind CSS 是一个用于快速UI开发的实用工具集 CSS 框架。与 Bootstrap 、Foundation 不同，Tailwind CSS 没有内置的 UI 组件。完全需要开发者根据自身情况来定制设计。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.jekyll.com.cn/&quot; title=&quot;Jekyll 是最流行的静态站点生成工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;jekyll&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/jekyll.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/jekyll.png&quot; alt=&quot;Jekyll 是最流行的静态站点生成工具。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.jekyll.com.cn/&quot; title=&quot;Jekyll 是最流行的静态站点生成工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;jekyll&#39;])&quot;&gt;Jekyll &lt;br&gt;&lt;small&gt;中文文档&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Jekyll 是一个静态站点生成工具。它将 Markdown （或者 Textile） 以及 Liquid 转化成一个完整的可发布的静态网站。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://hexo.bootcss.com/&quot; title=&quot;Hexo 是一个快速、简洁且高效的博客框架&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;hexo&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/hexo.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/hexo.png&quot; alt=&quot;Hexo 是一个快速、简洁且高效的博客框架&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://hexo.bootcss.com/&quot; title=&quot;Hexo 是一个快速、简洁且高效的博客框架&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;hexo&#39;])&quot;&gt;Hexo &lt;br&gt;&lt;small&gt;中文文档&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Hexo 是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown（或其他渲染引擎）解析文章，在几秒内，即可利用靓丽的主题生成静态网页。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.postcss.com.cn/&quot; title=&quot;PostCSS - 是一个用 JavaScript 工具和插件来转换 CSS 代码的工具&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;postcss&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/postcss.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/postcss.png&quot; alt=&quot;PostCSS - 是一个用 JavaScript 工具和插件来转换 CSS 代码的工具&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.postcss.com.cn/&quot; title=&quot;PostCSS - 是一个用 JavaScript 工具和插件来转换 CSS 代码的工具&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;postcss&#39;])&quot;&gt;PostCSS &lt;br&gt;&lt;small&gt;中文网&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;PostCSS 利用 JavaScript 的强大编程能力对 CSS 代码进行转换。数以百计的 PostCSS 插件可以用来为 CSS 属性添加特定于浏览器厂商的前缀、支持未来 CSS 语法、模块化、代码检测等。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://chartjs.bootcss.com/&quot; title=&quot;Chart.js 是为设计和开发人员准备的简单、灵活的 JavaScript 图表工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;chartjs&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/chartjs.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/chartjs.png&quot; alt=&quot;Chart.js 是为设计和开发人员准备的简单、灵活的 JavaScript 图表工具。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://chartjs.bootcss.com/&quot; title=&quot;Chart.js 是为设计和开发人员准备的简单、灵活的 JavaScript 图表工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;chartjs&#39;])&quot;&gt;Chart.js &lt;br&gt;&lt;small&gt;开源的 HTML5 图表工具&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Chart.js 是为设计和开发人员准备的简单、灵活的 JavaScript 图表工具。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.vuepress.cn/&quot; title=&quot;VuePress 是基于 Vue 前端开发框架的静态站点生成工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;vuepress&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/vuepress.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/vuepress.png&quot; alt=&quot;VuePress 是基于 Vue 前端开发框架的静态站点生成工具。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.vuepress.cn/&quot; title=&quot;VuePress 是基于 Vue 前端开发框架的静态站点生成工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;vuepress&#39;])&quot;&gt;VuePress &lt;br&gt;&lt;small&gt;基于 Vue 前端开发框架的静态站点生成工具&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;VuePress 是基于 Vue 前端开发框架的静态站点生成工具。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://nunjucks.bootcss.com/&quot; title=&quot;Nunjucks 是 JavaScript 专用的功能丰富、强大的模板引擎。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;nunjucks&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/nunjucks.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/nunjucks.png&quot; alt=&quot;Nunjucks 是 JavaScript 专用的功能丰富、强大的模板引擎。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://nunjucks.bootcss.com/&quot; title=&quot;Nunjucks 是 JavaScript 专用的功能丰富、强大的模板引擎。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;nunjucks&#39;])&quot;&gt;Nunjucks &lt;br&gt;&lt;small&gt;模板引擎&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Nunjucks 是 JavaScript 专用的功能丰富、强大的模板引擎。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://wasm.bootcss.com&quot; title=&quot;WebAssembly 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;webassembly&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/webassembly.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/webassembly.png&quot; alt=&quot;WebAssembly 中文文档&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://wasm.bootcss.com&quot; title=&quot;WebAssembly 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;webassembly&#39;])&quot;&gt;WebAssembly &lt;br&gt;&lt;small&gt;面向 web 应用的编译格式&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;WebAssembly 或者 wasm，是一种新型可移植，具有占用存储小，加载速度快等特点的面向 web 应用的编译格式。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.bundler.cn&quot; title=&quot;Bundler 是 Ruby 世界中最好的 gem 管理工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;bundler&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bundler.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bundler.png&quot; alt=&quot;Bundler 是 Ruby 世界中最好的 gem 管理工具。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.bundler.cn&quot; title=&quot;Bundler 是 Ruby 世界中最好的 gem 管理工具。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;bundler&#39;])&quot;&gt;Bundler &lt;br&gt;&lt;small&gt;是 Ruby 世界中最好的 gem 管理工具&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Bundler 是 Ruby 世界中最好的 gem 管理工具。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.quanzhanketang.com/&quot; title=&quot;w3schools 原版国内镜像&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;w3schools&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/w3schools.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/w3schools.png&quot; alt=&quot;w3schools 原版国内镜像&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.quanzhanketang.com/&quot; title=&quot;w3schools 原版国内镜像&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;w3schools&#39;])&quot;&gt;w3schools&lt;br&gt;&lt;small&gt;原版国内镜像&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;w3schools.com 是最受欢迎的前端技术教程网站，但是国内用户一直不能访问，并且国内的中文翻译版本十分陈旧。因此做了个镜像，希望英文好的同学直接去看原版教程吧！&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://nginx.bootcss.com&quot; title=&quot;Nginx 中文参考手册 - Nginx 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;nginx&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/nginx.jpg&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/nginx.jpg&quot; alt=&quot;Nginx 中文参考手册 - Nginx 中文文档&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://nginx.bootcss.com&quot; title=&quot;Nginx 中文参考手册 - Nginx 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;nginx&#39;])&quot;&gt;Nginx &lt;br&gt;&lt;small&gt;中文手册&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Nginx (engine x) 是一个高性能的HTTP和反向代理服务，也是一个IMAP/POP3/SMTP服务。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;https://www.sphinx.org.cn&quot; title=&quot;Sphinx 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;sphinx&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/sphinx.jpg&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/sphinx.jpg&quot; alt=&quot;Sphinx 中文文档&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;https://www.sphinx.org.cn&quot; title=&quot;Sphinx 中文文档&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;sphinx&#39;])&quot;&gt;Sphinx &lt;br&gt;&lt;small&gt;中文文档&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Sphinx 是一个用于构建文档的工具，最初是为 Python 文档而开发的。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/stickup/&quot; title=&quot;stickUp 能让页面目标元素“固定”在浏览器窗口的顶部&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;stickup&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/stickup.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/stickup.png&quot; alt=&quot;stickUp 能让页面目标元素“固定”在浏览器窗口的顶部&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/stickup/&quot; title=&quot;stickUp 能让页面目标元素“固定”在浏览器窗口的顶部&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;stickup&#39;])&quot;&gt;stickUp &lt;br&gt;&lt;small&gt;让页面元素“固定”位置&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;stickUp 能让页面目标元素“固定”在浏览器窗口的顶部，即便页面在滚动，目标元素仍然能出现在设定的位置。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/responsive-nav.js/&quot; title=&quot;响应式导航&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;navjs&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/responsive-nav.js.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/responsive-nav.js.png&quot; alt=&quot;响应式导航&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/responsive-nav.js/&quot; title=&quot;响应式导航&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;navjs&#39;])&quot;&gt;Responsive Nav &lt;br&gt;&lt;small&gt;响应式导航&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;响应式导航（Responsive Nav）是一个很小的JS插件，压缩之后仅有1.7KB，能帮你创建针对小屏幕的可切换式导航&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/unslider/&quot; title=&quot;Unslider&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;unslider&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/unslider.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/unslider.png&quot; alt=&quot;Unslider&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/unslider/&quot; title=&quot;Unslider&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;unslider&#39;])&quot;&gt;Unslider&lt;br&gt;&lt;small&gt;jQuery轮播插件&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Unslider - 一个超小的 jQuery 轮播（slider） 插件。支持主流浏览器、键盘导航、自动调整高度和响应式布局。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/flat-ui/&quot; title=&quot;Flat UI&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;flatui&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/flat-ui.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/flat-ui.png&quot; alt=&quot;Flat UI&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/flat-ui/&quot; title=&quot;Flat UI&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;flatui&#39;])&quot;&gt;Flat UI &lt;br&gt;&lt;small&gt;Metro 风格的 Bootstrap &lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Flat UI 是基于 Bootstrap 做的 Metro 化改造，由&lt;a href=&quot;http://designmodo.com/&quot;&gt;Designmodo&lt;/a&gt;提供。Flat UI包含了很多Bootstrap提供的组件，但是外观更加漂亮。在此强烈推荐！&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/layoutit/&quot; title=&quot;Bootstrap 可视化布局系统&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;layoutit&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/layoutit.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/layoutit.png&quot; alt=&quot;Bootstrap 可视化布局系统&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/layoutit/&quot; title=&quot;Bootstrap 可视化布局系统&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;layoutit&#39;])&quot;&gt;LayoutIt! &lt;br&gt;&lt;small&gt;Bootstrap 可视化布局&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;LayoutIt! 可拖放排序在线编辑的Bootstrap可视化布局系统。由&lt;a href=&quot;https://github.com/dodgepudding&quot; target=&quot;_blank&quot;&gt;4wer&lt;/a&gt;同学汉化整理。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/bootstrap-switch/&quot; title=&quot;Bootstrap Switch&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;switch&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bootstrap-switch.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bootstrap-switch.png&quot; alt=&quot;Bootstrap Switch&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/bootstrap-switch/&quot; title=&quot;Bootstrap Switch&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;switch&#39;])&quot;&gt;Bootstrap Switch &lt;br&gt;&lt;small&gt;Bootstrap 开关组件&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Bootstrap Switch 是对 Bootstrap 控件的扩充。基于选 HTML 中基本的选择框控件实现只有开和关两种状态的单选按钮。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/sco.js/&quot; title=&quot;Sco.js&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;Sco.js&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/sco.js.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/sco.js.png&quot; alt=&quot;Sco.js&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/sco.js/&quot; title=&quot;Sco.js&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;Sco.js&#39;])&quot;&gt;Sco.js &lt;br&gt;&lt;small&gt;Bootstrap 组件增强版&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;由于大部分的 Bootstrap js 插件是无法扩展的，因此才有了 sco.js，它是对 Bootsrap 中 js 插件的增强实现。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/icheck/&quot; title=&quot;iCheck&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;icheck&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/icheck.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/icheck.png&quot; alt=&quot;iCheck&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/icheck/&quot; title=&quot;iCheck&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;icheck&#39;])&quot;&gt;iCheck &lt;br&gt;&lt;small&gt;增强复选框和单选按钮&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;iCheck 让不同浏览器下的复选框（checkboxes）和单选按钮（radio button）更美观、功能更强。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/bootstrap-wysiwyg/&quot; title=&quot;bootstrap-wysiwyg&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;wysiwyg&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bootstrap-wysiwyg.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bootstrap-wysiwyg.png&quot; alt=&quot;bootstrap-wysiwyg&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/bootstrap-wysiwyg/&quot; title=&quot;bootstrap-wysiwyg&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;wysiwyg&#39;])&quot;&gt;bootstrap-wysiwyg&lt;br&gt;&lt;small&gt;为Bootstrap定制的可视编辑器&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;bootstrap-wysiwyg 是一个 jQuery Bootstrap 插件（5KB, 200 行代码）可以将任何一个 div 转变成一个 WYSIWYG 富文本编辑器。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/preboot/&quot; title=&quot;Preboot&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;preboot&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/preboot.png&quot; alt=&quot;Preboot&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/preboot/&quot; title=&quot;Preboot&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;preboot&#39;])&quot;&gt;Preboot &lt;br&gt;&lt;small&gt;Bootstrap 的前世&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Preboot 是一组用 less 语法书写的混合（mixin）和变量（variable）的集合，目的是辅助用户书写更优美的CSS。Bootstrap的前身就是Preboot。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/jquery.pin/&quot; title=&quot;jQuery.Pin&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;pin&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/jquery.pin.png&quot; alt=&quot;jQuery.Pin&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/jquery.pin/&quot; title=&quot;jQuery.Pin&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;pin&#39;])&quot;&gt;jQuery.Pin &lt;br&gt;&lt;small&gt;固定页面元素的 jQuery 插件&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;jQuery.Pin 能将任意页面元素“钉”在某个容器顶部，而且在尺寸小的屏幕上能够自动禁用这种效果。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/bsie/&quot; title=&quot;Bootstrap IE6兼容方案&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;bsie&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bsie.png&quot; alt=&quot;Bootstrap IE6兼容方案&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/bsie/&quot; title=&quot;Bootstrap IE6兼容方案&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;bsie&#39;])&quot;&gt;Bsie &lt;br&gt;&lt;small&gt;Bootstrap IE6 兼容方案&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Bsie 弥补了 Bootstrap 对 IE6 的不兼容。目前，bsie 能在 IE6 上支持大部分 bootstrap 的特性，可惜，还有一些实在无法支持...&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/messenger/&quot; title=&quot;非常酷的弹框(Alert)组件&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;messenger&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/messenger.png&quot; alt=&quot;非常酷的弹框(Alert)组件&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/messenger/&quot; title=&quot;非常酷的弹框(Alert)组件&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;messenger&#39;])&quot;&gt;Messenger&lt;br&gt;&lt;small&gt;非常酷的弹框(Alert)组件&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Messenger 是一个非常酷的弹框(Alert)组件，能够非常好的与 Bootstrap 融合，当然，单独使用效果也是非常棒。Messenger 自带4套皮肤。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/bootstrap-datetimepicker/&quot; title=&quot;Bootstrap 日期时间选择器&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;datetimepicker&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bootstrap-datetimepicker.png&quot; alt=&quot;Bootstrap 日期时间选择器&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/bootstrap-datetimepicker/&quot; title=&quot;Bootstrap 日期时间选择器&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;datetimepicker&#39;])&quot;&gt;DateTime Picker &lt;br&gt;&lt;small&gt;日期时间选择器&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Bootstrap 日期时间选择器（Bootstrap DateTime Picker）是一个 Bootstrap 组件，能够简化页面上日期、时间的输入。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/jquery-ui-bootstrap/&quot; title=&quot;基于 Bootstrap 样式的 jQuery UI 控件&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;jquibootstrap&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/jquery-ui-bootstrap.png&quot; alt=&quot;基于 Bootstrap 样式的 jQuery UI 控件&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/jquery-ui-bootstrap/&quot; title=&quot;基于 Bootstrap 样式的 jQuery UI 控件&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;jquibootstrap&#39;])&quot;&gt;jQuery UI Bootstrap &lt;br&gt;&lt;small&gt;用 Bootstrap 美化 jQuery UI&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;这套工具让你在使用 jQuery UI 控件时也能充分利用 Bootstrap 的样式，而且不会出现样式不统一的现象，Bootstrap 和 jQuery UI 可以完美融合在一起了！&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/google-bootstrap/&quot; title=&quot;Google 风格的 Bootstrap&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;googlebootstrap&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/google-bootstrap.png&quot; alt=&quot;Google 风格的 Bootstrap&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/google-bootstrap/&quot; title=&quot;Google 风格的 Bootstrap&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;googlebootstrap&#39;])&quot;&gt;Google Bootstrap &lt;br&gt;&lt;small&gt;Google 风格的 Bootstrap&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Google 的 UI 素来以简洁著称，现在 Bootstrap 也来 Google Style 一把，喜欢 Google 的就来试试这套 Google Bootstrap 吧！&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/metro-ui-css/&quot; title=&quot;Bootstrap Metro UI CSS&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;metrouicss&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/metro-ui-css.png&quot; alt=&quot;Bootstrap Metro UI CSS&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/metro-ui-css/&quot; title=&quot;Bootstrap Metro UI CSS&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;metrouicss&#39;])&quot;&gt;Metro UI CSS &lt;br&gt;&lt;small&gt;Bootstrap 与 Metro 融合&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Metro UI CSS 是一套用来创建类似于 Windows 8 Metro UI 风格网站的样式。现在，Metro UI CSS 项目在 Bootstrap 的基础上被开发成一个独立的解决方案。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/font-awesome/&quot; title=&quot;Font Awesome&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;fontawesome&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/font-awesome.png&quot; alt=&quot;Font Awesome&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/font-awesome/&quot; title=&quot;Font Awesome&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;fontawesome&#39;])&quot;&gt;Font Awesome &lt;br&gt;&lt;small&gt; Bootstrap 专用图标字体&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Font Awesome 中包含的所有图标都是矢量的，也就可以任意缩放，避免了一个图标做多种尺寸的麻烦。CSS 对字体可以设置的样式也同样能够运用到这些图标上了。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/simple-icons/&quot; title=&quot;Icon汇&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;simpleicons&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/simpleicons.png&quot; alt=&quot;Icon汇&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/simple-icons/&quot; title=&quot;Icon汇&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;simpleicons&#39;])&quot;&gt;Simple Icons&lt;br&gt;&lt;small&gt;Icon汇&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Simple Icons -- Icon汇。收集众多网站的 Logo，并提供高质量、不同尺寸的 png 格式图片给广大网友，所有 Icon 版权归其所属公司。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/bootstrap-form-builder/&quot; title=&quot;Bootstrap 在线表单构造器&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;bsformbuilder&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bootstrap-form-builder.png&quot; alt=&quot;Bootstrap 在线表单构造器&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/bootstrap-form-builder/&quot; title=&quot;Bootstrap 在线表单构造器&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;bsformbuilder&#39;])&quot;&gt;Bootstrap  Form Builder&lt;br&gt;&lt;small&gt;在线表单构造器&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Bootstrap 在线表单构造器能够以鼠标拖拽的方式迅速生成一个基于 Bootstrap 的完整表单，减轻了各位码农手写HTML代码的劳动，而且不会出错。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/html5boilerplate/&quot; title=&quot;HTML5 Boilerplate&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;h5boilerplate&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/h5bp.png&quot; alt=&quot;HTML5 Boilerplate&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/html5boilerplate/&quot; title=&quot;HTML5 Boilerplate&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;h5boilerplate&#39;])&quot;&gt;HTML5 Boilerplate &lt;br&gt;&lt;small&gt;专业的前端模版&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;HTML5 Boilerplate 是一套专业的前端模版，用以开发快速、健壮、适应性强的 app 或网站。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/websafecolors/&quot; title=&quot;Web 安全色&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;websafecolors&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/websafecolors.png&quot; alt=&quot;Web 安全色&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/websafecolors/&quot; title=&quot;Web 安全色&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;websafecolors&#39;])&quot;&gt;Web Safe Colors &lt;br&gt;&lt;small&gt;Web 安全色&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;本表中列出的是 WEB 设计、开发中常用安全色。列于此是为了方便大家参考。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;http://docs.bootcss.com/&quot; title=&quot;Bootstrap 文档全集&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;docs&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/bootstrap-docs.png&quot; alt=&quot;Bootstrap 文档全集&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;http://docs.bootcss.com/&quot; title=&quot;Bootstrap 文档全集&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;docs&#39;])&quot;&gt;Bootstrap Docs &lt;br&gt;&lt;small&gt;Bootstrap 文档全集&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;这里收集了 Bootstrap 从 V1.0.0 版本到现在，整个文档的历史。Bootstrap 本身就是一个传奇，而这些文档就是传奇的见证！&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/git-guide/&quot; title=&quot;Git 简易指南&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;gitguide&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/git-guide.png&quot; alt=&quot;Git 简易指南&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/git-guide/&quot; title=&quot;Git 简易指南&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;gitguide&#39;])&quot;&gt;Git Guide &lt;br&gt;&lt;small&gt;Git 简易指南&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Git简易指南 -- 帮助你开始使用 git 的简易指南，木有高深内容，;)。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/grumblejs/&quot; title=&quot;气泡形状的提示（Tooltip）控件&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;grumblejs&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/grumblejs.png&quot; alt=&quot;气泡形状的提示（Tooltip）控件&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/grumblejs/&quot; title=&quot;气泡形状的提示（Tooltip）控件&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;grumblejs&#39;])&quot;&gt;Grumble.js &lt;br&gt;&lt;small&gt;气泡形状的提示（Tooltip）控件&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;一个气泡形状的提示（Tooltip）控件，可以在其围绕的元素周围做360度任意定位。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/cikonss/&quot; title=&quot;纯 CSS 实现的 Icon&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;cikonss&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/cikonss.png&quot; alt=&quot;纯 CSS 实现的 Icon&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/cikonss/&quot; title=&quot;纯 CSS 实现的 Icon&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;cikonss&#39;])&quot;&gt;CIKONSS &lt;br&gt;&lt;small&gt;纯 CSS 实现的 Icon&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Cikonss 是纯 CSS 实现的响应式 Icon，兼容 IE8+。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/headroom.js/&quot; title=&quot;Headroom.js 是一个轻量级、纯 JS 组件，用来隐藏或展现页面上的元素，为你的页面留下更多展示内容的空间。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;headroom&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/headroom.png&quot; alt=&quot;Headroom.js 是一个轻量级、纯 JS 组件，用来隐藏或展现页面上的元素，为你的页面留下更多展示内容的空间。&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/headroom.js/&quot; title=&quot;Headroom.js 是一个轻量级、纯 JS 组件，用来隐藏或展现页面上的元素，为你的页面留下更多展示内容的空间。&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;headroom&#39;])&quot;&gt;Headroom.js &lt;br&gt;&lt;small&gt;隐藏或展示页面元素&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Headroom.js 是一个轻量级、纯 JavaScript 组件，用来隐藏或展现页面上的元素，为你的页面留下更多展示内容的空间。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;      &lt;div class=&quot;col-sm-6 col-md-4 col-lg-3 &quot;&gt;      &lt;div class=&quot;thumbnail&quot; style=&quot;height: 336px;&quot;&gt;        &lt;a href=&quot;/p/buttons/&quot; title=&quot;基于 Sass 和 Compass 构建的CSS按钮（button）样式库&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;button&#39;])&quot;&gt;          &lt;img class=&quot;lazy&quot; src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/null.png&quot; width=&quot;300&quot; height=&quot;150&quot; data-src=&quot;https://cdn.jsdelivr.net/npm/@bootcss/www.bootcss.com@0.0.3/dist/img/buttons.png&quot; alt=&quot;基于 Sass 和 Compass 构建的CSS按钮（button）样式库&quot;&gt;        &lt;/a&gt;        &lt;div class=&quot;caption&quot;&gt;          &lt;h3&gt;              &lt;a href=&quot;/p/buttons/&quot; title=&quot;基于 Sass 和 Compass 构建的CSS按钮（button）样式库&quot; target=&quot;_blank&quot; onclick=&quot;_hmt.push([&#39;_trackEvent&#39;, &#39;tile&#39;, &#39;click&#39;, &#39;button&#39;])&quot;&gt;Buttons &lt;br&gt;&lt;small&gt;CSS 按钮样式库&lt;/small&gt;&lt;/a&gt;          &lt;/h3&gt;          &lt;p&gt;Buttons 是一个基于 Sass 和 Compass 构建的CSS按钮（button）样式库，图标采用的是&lt;a href=&quot;/p/font-awesome/&quot; target=&quot;_blank&quot;&gt;Font Awesome&lt;/a&gt;，可以和 Bootstrap 融合使用。&lt;/p&gt;        &lt;/div&gt;      &lt;/div&gt;    &lt;/div&gt;  &lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Bootstrap介绍</title>
      <link href="front/bootstrap/bootstrap-introduce/"/>
      <url>front/bootstrap/bootstrap-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="Bootstrap-简介"><a href="#Bootstrap-简介" class="headerlink" title="Bootstrap 简介"></a>Bootstrap 简介</h3><p>什么是 Bootstrap？<br>Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的。</p><p>Bootstrap 目前的最新版本是 Bootstrap4，利用我们提供的 Sass 变量和大量 mixin、响应式栅格系统、可扩展的预制组件、基于 jQuery 的强大的插件系统，能够快速为你的想法开发出原型或者构建整个 app 。</p><p>历史<br>Bootstrap 是由 Twitter 的 Mark Otto 和 Jacob Thornton 开发的。Bootstrap 是 2011 年八月在 GitHub 上发布的开源产品。</p><h3 id="为什么使用-Bootstrap？"><a href="#为什么使用-Bootstrap？" class="headerlink" title="为什么使用 Bootstrap？"></a>为什么使用 Bootstrap？</h3><ul><li><p>移动设备优先：自 Bootstrap 3 起，框架包含了贯穿于整个库的移动设备优先的样式。</p></li><li><p>浏览器支持：所有的主流浏览器都支持 Bootstrap。</p><ul><li>Internet Explorer  </li><li>Firefox  </li><li>Opera  </li><li>Google Chrome  </li><li>Safari</li></ul></li><li><p>容易上手：只要您具备 HTML 和 CSS 的基础知识，您就可以开始学习 Bootstrap。</p></li><li><p>响应式设计：Bootstrap 的响应式 CSS 能够自适应于台式机、平板电脑和手机。</p></li><li><p>它为开发人员创建接口提供了一个简洁统一的解决方案。</p></li><li><p>它包含了功能强大的内置组件，易于定制。</p></li><li><p>它还提供了基于 Web 的定制。</p></li><li><p>它是开源的。</p></li></ul><h3 id="Bootstrap-包的内容"><a href="#Bootstrap-包的内容" class="headerlink" title="Bootstrap 包的内容"></a>Bootstrap 包的内容</h3><ul><li><p>基本结构：Bootstrap 提供了一个带有网格系统、链接样式、背景的基本结构。这将在 Bootstrap 基本结构 部分详细讲解。</p></li><li><p>CSS：Bootstrap 自带以下特性：全局的 CSS 设置、定义基本的 HTML 元素样式、可扩展的 class，以及一个先进的网格系统。这将在 Bootstrap CSS 部分详细讲解。</p></li><li><p>组件：Bootstrap 包含了十几个可重用的组件，用于创建图像、下拉菜单、导航、警告框、弹出框等等。这将在 布局组件 部分详细讲解。</p></li><li><p>JavaScript 插件：Bootstrap 包含了十几个自定义的 jQuery 插件。您可以直接包含所有的插件，也可以逐个包含这些插件。这将在 Bootstrap 插件 部分详细讲解。</p></li><li><p>定制：您可以定制 Bootstrap 的组件、LESS 变量和 jQuery 插件来得到您自己的版本。</p></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> Bootstrap </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Bootstrap 编程实战闯关</title>
      <link href="front/bootstrap/bootstrap-practice/"/>
      <url>front/bootstrap/bootstrap-practice/</url>
      
        <content type="html"><![CDATA[<div class="project-body"><div class="portlet-title pro-title" style="width: 1601px;"><div class="set-btn-group font-settings pull-left"><a href="javascript:;" class="expand-collapse-trigger" title="折叠/展开"><i class="icon-th-list"></i></a><a href="javascript:;" class="toggle-dropdown" title="视觉主题设置"><i class="icon-font"></i></a><div class="set-dropdown-menu docblur" style="display:none;"><div class="dropdown-caret"><span class="caret-outer"></span><span class="caret-inner"></span></div><div class="buttons font-opt"><button class="button size font-reduce" font="reduce">A</button><button class="button size font-enlarge" font="enlarge">A</button></div><div class="buttons bg-color"><button class="button theme" color="color-theme-white" title="默认模式">默认</button><button class="button theme" color="color-theme-sepia" title="护眼模式">护眼</button><button class="button theme" color="color-theme-night" title="夜间模式">夜间</button></div></div></div><div class="kn-btn-group pull-right">            <span id="content-head-viewcount" class="viewcount-btn"><i class="icon-eye-open"></i> <span>阅读(125.3k)</span></span><a id="knstar" href="javascript:;" onclick="isstar()" data-type="star"><i class="icon-bookmark-empty"></i> <span>书签</span></a><a class="btn-thumbs-up" href="javascript:;" onclick="islike()"><i class="icon-thumbs-up"></i> <span id="likestatus">赞</span>(<span id="likecount">36</span>)</a><a href="javascript:;" title="分享" class="share-btn  popup_more bdsharebuttonbox bdshare-button-style0-16" data-cmd="more" data-bd-bind="1568889511672"><i class="icon-share"></i> 分享</a><a id="correct" href="/edit/bootstrap/bootstrap-codecamp" rel="nofollow"><i class="icon-edit"></i> <span>我要纠错</span></a><div class="pro-tools"><a class="toggle-dropdown" href="#"><i class="icon-ellipsis-horizontal"></i></a><ul class="dropdown-menu docblur" style="display: none;">   <li><a href="javascript:;" title="收录专题" data-ctype="kn" id="collection"><i class="icon-inbox"></i> 收录专题</a></li>                          </ul></div></div></div><div id="pro-mian-header"><div class="content-top"><h1>Bootstrap 编程实战闯关</h1></div><div class="kn-infomation">由&nbsp;<span>843622626</span>&nbsp;创建，Carrie 最后一次修改&nbsp;<span>2016-10-27</span>    </div>          </div>          <div class="content-bg"><div class="content-intro view-box "><p>为了帮助广大学习者，做到学以致用，我们为大家准备了大量的Bootstrap编程实战题，通过这些实战题，您可以一边学习一边操作，来达到巩固学习的作用。</p><p>请选择你喜欢的实战题，开始进行编程闯关。</p><p></p><div><h2>Bootstrap课程列表</h2></div><div><ul><li><h4><a href="//www.w3cschool.cn/codecamp/use-responsive-design-with-bootstrap-fluid-containers.html" title="h" target="_self">使用Bootstrap设计响应式页面</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/make-images-mobile-responsive.html" title="h" target="_self">通过Bootstrap使图片适配手机显示</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/center-text-with-bootstrap.html" title="h" target="_self">通过Bootstrap使文本居中</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/create-a-bootstrap-button.html" title="h" target="_self">通过Bootstrap添加一个按钮</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/create-a-block-element-bootstrap-button.html" title="h" target="_self">添加一个Bootstrap块级元素按钮</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/taste-the-bootstrap-button-color-rainbow.html" title="h" target="_self">尝试给一个Bootstrap按钮添加颜色</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/call-out-optional-actions-with-button-info.html" title="h" target="_self">Bootstrap按钮多种颜色属性设定</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/warn-your-users-of-a-dangerous-action.html" title="h" target="_self">添加一个Bootstrap警告按钮</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/use-the-bootstrap-grid-to-put-elements-side-by-side.html" title="h" target="_self">使用Bootstrap做页面布局</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/ditch-custom-css-for-bootstrap.html" title="h" target="_self">为Bootstrap定义自定义CSS</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/use-spans-for-inline-elements.html" title="h" target="_self">使用Bootstrap span标签来创建行内元素</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/create-a-custom-heading.html" title="h" target="_self">使用Bootstrap设计一个头部导航</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/add-font-awesome-icons-to-our-buttons.html" title="h" target="_self">在按钮上使用Font Awesome图标</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/add-font-awesome-icons-to-all-of-our-buttons.html" title="h" target="_self">为所有按钮添加Font Awesome图标</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/responsively-style-radio-buttons.html" title="h" target="_self">使用Bootstrap 响应式单选按钮</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/responsively-style-checkboxes.html" title="h" target="_self">使用Bootstrap 响应式复选框</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/style-text-inputs-as-form-controls.html" title="h" target="_self">使用Form Controls设置输入框样式</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/line-up-form-elements-responsively-with-bootstrap.html" title="h" target="_self">使用Bootstrap水平排列的表单</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/create-a-bootstrap-headline.html" title="h" target="_self">使用Bootstrap创建一个头部标题</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/house-our-page-within-a-bootstrap-container-fluid-div.html" title="h" target="_self">使用Bootstrap设置一个div容器为响应式的</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/create-a-bootstrap-row.html" title="h" target="_self">添加一个Bootstrap行容器</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/split-your-bootstrap-row.html" title="h" target="_self">分割Bootstrap行容器</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/create-bootstrap-wells.html" title="h" target="_self">添加Bootstrap well容器</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/add-elements-within-your-bootstrap-wells.html" title="h" target="_self">在Bootstrap well容器中加按钮</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/apply-the-default-bootstrap-button-style.html" title="h" target="_self">设定Bootstrap按钮的样式</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/create-a-class-to-target-with-jquery-selectors.html" title="h" target="_self">通过添加class成为jQuery的选择器</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/add-id-attributes-to-bootstrap-elements.html" title="h" target="_self">为Bootstrap元素添加ID属性</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/label-bootstrap-wells.html" title="h" target="_self">为Bootstrap well添加标签</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/give-each-element-a-unique-id.html" title="h" target="_self">给每一个Bootstrap 按钮添加不同的ID</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/label-bootstrap-buttons.html" title="h" target="_self">为Bootstrap按钮添加文本</a></h4></li><li><h4><a href="//www.w3cschool.cn/codecamp/use-comments-to-clarify-code.html" title="h" target="_self">使用注释标签说明代码</a></h4></li></ul></div><p></p></div><div style="clear:both"></div></div><!--我要赞赏--><div class="project-sq"><div class="project-sq-info"><span>您的支持将鼓励我们做得更好</span></div><ul class="project-sq-avatar"></ul><div class="project-sq-btnarea"><a href="javascript:;">赞赏支持</a></div></div><!--我要赞赏结束--><!--我要评价--><div id="evaluate-box"><span id="evaluates">以上内容是否对您有帮助：</span><span class="star_score"><span title="1分"></span><span title="2分"></span><span title="3分"></span><span title="4分"></span><span title="5分"></span></span></div><!--我要评价结束--><div class="content-links"><div class="previous-link">← <a data-id="bootstrap-environment-setup" title="上一篇：Bootstrap 环境安装">Bootstrap 环境安装</a></div><div class="next-link"><a data-id="bootstrap-css-overview" title="下一篇：Bootstrap CSS 概览">Bootstrap CSS 概览</a> →</div></div><!--练习、出题、写笔记--><div class="project-operation"><!-- <div class="pull-left"><a href="/exam/knowledgetest?pname=bootstrap&amp;kname=bootstrap-codecamp" style="display:none" target="_blank" class="op-btn exam-btn" id="kn-test"><i class="icon-magic"></i>测试一下</a><a href="/minicourse/textureknowledge?pname=bootstrap&amp;kname=bootstrap-codecamp" rel="nofollow" target="_blank" class="op-btn make-btn" id="kn-textureexam"><i class="icon-plus-sign"></i>我要出题</a></div> --><div class="pull-right"><a href="javascript:;" class="op-btn note-btn" onclick="openNote()"><i class="icon-pencil"></i>写笔记</a></div></div><!--横版广告放置--><div class="abox-item">    <div class="abox-content">    </div></div> <!-- 笔记列表 --><div class="notelist-box notelist-box2" style="display:none"><div class="notelist-head" onclick="openNoteList(this)"><span class="notelist-title">精选笔记</span><i class="icon-circle-arrow-up"></i></div><div class="notelist-content" id="notelist_content" style="display: none;"></div></div></div>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> Bootstrap </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>啥是Layui</title>
      <link href="front/layui/layui-introduce/"/>
      <url>front/layui/layui-introduce/</url>
      
        <content type="html"><![CDATA[<p><img src= "/img/loading.gif" data-lazy-src="/img/posts/layui/layui.png" alt="img"></p><h3 id="开始使用"><a href="#开始使用" class="headerlink" title="开始使用"></a>开始使用</h3><p>layui（谐音：类UI) 是一款采用自身模块规范编写的前端 UI 框架，遵循原生 HTML/CSS/JS 的书写与组织形式，门槛极低，拿来即用。其外在极简，却又不失饱满的内在，体积轻盈，组件丰盈，从核心代码到 API 的每一处细节都经过精心雕琢，非常适合界面的快速开发。layui  首个版本发布于 2016 年金秋，她区别于那些基于 MVVM 底层的 UI 框架，却并非逆道而行，而是信奉返璞归真之道。准确地说，她更多是为服务端程序员量身定做，你无需涉足各种前端工具的复杂配置，只需面对浏览器本身，让一切你所需要的元素与交互，从这里信手拈来。</p><h3 id="兼容性和面向场景"><a href="#兼容性和面向场景" class="headerlink" title="兼容性和面向场景"></a>兼容性和面向场景</h3><p>layui 兼容人类正在使用的全部浏览器（IE6/7除外），可作为 PC 端后台系统与前台界面的速成开发方案。</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> Layui </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>啥是静默注释</title>
      <link href="front/sass/sass-Silent%20comment/"/>
      <url>front/sass/sass-Silent%20comment/</url>
      
        <content type="html"><![CDATA[<h3 id="css中的注释"><a href="#css中的注释" class="headerlink" title="css中的注释"></a>css中的注释</h3><div class="content-bg"><div class="content-intro view-box "><p></p><p><code>css</code>中注释的作用包括帮助你组织样式、以后你看自己的代码时明白为什么这样写，以及简单的样式说明。但是，你并不希望每个浏览网站源码的人都能看到所有注释。</p><h3>sass中的注释</h3><p><code>sass</code>另外提供了一种不同于<code>css</code>标准注释格式<code>/* ... */</code>的注释语法，即静默注释，其内容不会出现在生成的<code>css</code>文件中。静默注释的语法跟<code>JavaScript</code><code>Java</code>等类<code>C</code>的语言中单行注释的语法相同，它们以<code>//</code>开头，注释内容直到行末。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs cpp"><span>body</span> &#123;  <span>color</span><span>: <span>#<span class="hljs-number">333</span></span>;</span> <span><span class="hljs-comment">// 这种注释内容不会出现在生成的css文件中</span></span>  <span>padding</span><span>: <span><span class="hljs-number">0</span></span>;</span> <span><span class="hljs-comment">/* 这种注释内容会出现在生成的css文件中 */</span></span>&#125;</code></pre><p>实际上，<code>css</code>的标准注释格式<code>/* ... */</code>内的注释内容亦可在生成的<code>css</code>文件中抹去。当注释出现在原生<code>css</code>不允许的地方，如在<code>css</code>属性或选择器中，<code>sass</code>将不知如何将其生成到对应<code>css</code>文件中的相应位置，于是这些注释被抹掉。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs php"><span>body</span> &#123;  <span>color</span> <span><span class="hljs-comment">/* 这块注释内容不会出现在生成的css中 */</span></span><span>: <span><span class="hljs-comment">#333</span></span><span class="hljs-comment">;</span></span>  <span>padding</span><span>: <span><span class="hljs-number">1</span></span>;</span> <span><span class="hljs-comment">/* 这块注释内容也不会出现在生成的css中 */</span></span> <span class="hljs-number">0</span>;&#125;</code></pre><p>你已经掌握了<code>sass</code>的静默注释，了解了保持<code>sass</code>条理性和可读性的最基本的三个方法:嵌套、导入和注释。现在，我们要进一步学习新特性，这样我们不但能保持条理性还能写出更好的样式。首先要介绍的内容是:使用混合器抽象你的相关样式。</p></div><div style="clear:both"></div></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sass中父选择器的标识符&amp;</title>
      <link href="front/sass/sass-father-select-and/"/>
      <url>front/sass/sass-father-select-and/</url>
      
        <content type="html"><![CDATA[<h3 id="启航"><a href="#启航" class="headerlink" title="启航"></a>启航</h3><div class="content-intro view-box "><p></p><p> 一般情况下，<code>sass</code>在解开一个嵌套规则时就会把父选择器(<code>#content</code>)通过一个空格连接到子选择器的前边(<code>article</code>和<code>aside</code>)形成(<code>#content article</code>和<code>#content aside</code>)。这种在CSS里边被称为后代选择器，因为它选择ID为<code>content</code>的元素内所有命中选择器<code>article</code>和<code>aside</code>的元素。但在有些情况下你却不会希望<code>sass</code>使用这种后代选择器的方式生成这种连接。</p><p>最常见的一种情况是当你为链接之类的元素写<code>:hover</code>这种伪类时，你并不希望以后代选择器的方式连接。比如说，下面这种情况<code>sass</code>就无法正常工作:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs ruby"><span>article</span> <span>a</span> &#123;  <span><span class="hljs-symbol"><span class="hljs-symbol">color</span></span></span><span><span class="hljs-symbol"><span class="hljs-symbol">:</span></span> blue;</span>  <span><span class="hljs-symbol"><span class="hljs-symbol">:hover</span></span></span> &#123; <span><span class="hljs-symbol"><span class="hljs-symbol">color</span></span></span><span><span class="hljs-symbol"><span class="hljs-symbol">:</span></span> red &#125;&#125;</span></code></pre><p>这意味着<code>color: red</code>这条规则将会被应用到选择器<code>article a :hover</code>，<code>article</code>元素内链接的所有子元素在被<code>hover</code>时都会变成红色。这是不正确的！你想把这条规则应用到超链接自身，而后代选择器的方式无法帮你实现。</p><p>解决之道为使用一个特殊的<code>sass</code>选择器，即父选择器。在使用嵌套规则时，父选择器能对于嵌套规则如何解开提供更好的控制。它就是一个简单的<code>&amp;</code>符号，且可以放在任何一个选择器可出现的地方，比如<code>h1</code>放在哪，它就可以放在哪。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs ruby"><span>article</span> <span>a</span> &#123;  <span><span class="hljs-symbol"><span class="hljs-symbol">color</span></span></span><span><span class="hljs-symbol"><span class="hljs-symbol">:</span></span> blue;</span>  &amp;<span><span class="hljs-symbol"><span class="hljs-symbol">:hover</span></span></span> &#123; <span><span class="hljs-symbol"><span class="hljs-symbol">color</span></span></span><span><span class="hljs-symbol"><span class="hljs-symbol">:</span></span> red &#125;&#125;</span></code></pre><p>当包含父选择器标识符的嵌套规则被打开时，它不会像后代选择器那样进行拼接，而是<code>&amp;</code>被父选择器直接替换:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag"><span class="hljs-selector-tag">article</span></span></span> <span><span class="hljs-selector-tag"><span class="hljs-selector-tag">a</span></span></span> <span>&#123; <span><span><span class="hljs-attribute"><span class="hljs-attribute">color</span></span></span>:<span> blue </span></span></span>&#125;<span><span class="hljs-selector-tag"><span class="hljs-selector-tag">article</span></span></span> <span><span class="hljs-selector-tag"><span class="hljs-selector-tag">a</span></span></span><span><span class="hljs-selector-pseudo"><span class="hljs-selector-pseudo">:hover</span></span></span> <span>&#123; <span><span><span class="hljs-attribute"><span class="hljs-attribute">color</span></span></span>:<span> red </span></span></span>&#125;</code></pre><p>在为父级选择器添加<code>:hover</code>等伪类时，这种方式非常有用。同时父选择器标识符还有另外一种用法，你可以在父选择器之前添加选择器。举例来说，当用户在使用IE浏览器时，你会通过<code>JavaScript</code>在<code></code>标签上添加一个ie的类名，为这种情况编写特殊的样式如下:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs markdown"><span><span class="hljs-section"><span class="hljs-section">#content</span></span></span><span class="hljs-section"><span class="hljs-section"> </span></span><span><span class="hljs-section"><span class="hljs-section">aside</span></span></span><span class="hljs-section"><span class="hljs-section"> &#123;</span></span>  <span>color</span><span>: red;</span>  <span>body</span><span>.ie</span> &amp; &#123; <span>color</span><span>: green &#125;&#125;</span></code></pre><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-comment"><span class="hljs-comment">/*编译后*/</span></span></span><span><span class="hljs-selector-id"><span class="hljs-selector-id">#content</span></span></span> <span><span class="hljs-selector-tag"><span class="hljs-selector-tag">aside</span></span></span> <span>&#123;<span><span><span class="hljs-attribute"><span class="hljs-attribute">color</span></span></span>:<span> red</span></span></span>&#125;;<span><span class="hljs-selector-tag"><span class="hljs-selector-tag">body</span></span></span><span><span class="hljs-selector-class"><span class="hljs-selector-class">.ie</span></span></span> <span><span class="hljs-selector-id"><span class="hljs-selector-id">#content</span></span></span> <span><span class="hljs-selector-tag"><span class="hljs-selector-tag">aside</span></span></span> <span>&#123; <span><span><span class="hljs-attribute"><span class="hljs-attribute">color</span></span></span>:<span> green </span></span></span>&#125;</code></pre><p><code>sass</code>在选择器嵌套上是非常智能的，即使是带有父选择器的情况。当<code>sass</code>遇到群组选择器(由多个逗号分隔开的选择器形成)也能完美地处理这种嵌套。</p><br></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sass中群组选择器的嵌套</title>
      <link href="front/sass/sass-group-select/"/>
      <url>front/sass/sass-group-select/</url>
      
        <content type="html"><![CDATA[<h3 id="启航"><a href="#启航" class="headerlink" title="启航"></a>启航</h3><div class="content-bg"><div class="content-intro view-box "><p></p><p>在<code>CSS</code>里边，选择器<code>h1</code><code>h2</code>和<code>h3</code>会同时命中h1元素、h2元素和h3元素。与此类似，<code>.button</code><code>button</code>会命中button元素和类名为.button的元素。这种选择器称为群组选择器。群组选择器的规则会对命中群组中任何一个选择器的元素生效。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-class">.button</span></span>, <span><span class="hljs-selector-tag">button</span></span> <span>&#123;  <span><span><span class="hljs-attribute">margin</span></span>:<span> <span><span class="hljs-number">0</span></span></span></span>;<span>&#125;</span></span></code></pre><p>当看到上边这段代码时，你可能还没意识到会有重复性的工作。但会很快发现:如果你需要在一个特定的容器元素内对这样一个群组选择器进行修饰，情况就不同了。<code>css</code>的写法会让你在群组选择器中的每一个选择器前都重复一遍容器元素的选择器。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-class">.container</span></span> <span><span class="hljs-selector-tag">h1</span></span>, <span><span class="hljs-selector-class">.container</span></span> <span><span class="hljs-selector-tag">h2</span></span>, <span><span class="hljs-selector-class">.container</span></span> <span><span class="hljs-selector-tag">h3</span></span> <span>&#123; <span><span><span class="hljs-attribute">margin-bottom</span></span>:<span> .<span><span class="hljs-number">8em</span></span> </span></span></span>&#125;</code></pre><p>非常幸运，<code>sass</code>的嵌套特性在这种场景下也非常有用。当<code>sass</code>解开一个群组选择器规则内嵌的规则时，它会把每一个内嵌选择器的规则都正确地解出来:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs"><span>.container</span> &#123;  <span>h1</span>, <span>h2</span>, <span>h3</span> &#123;<span>margin-bottom</span><span>: .<span>8em</span>&#125;&#125;</span></code></pre><p>首先<code>sass</code>将<code>.container</code>和<code>h1</code><code>.container</code>和<code>h2</code><code>.container</code>和<code>h3</code>分别组合，然后将三者重新组合成一个群组选择器，生成你前边看到的普通<code>css</code>样式。对于内嵌在群组选择器内的嵌套规则，处理方式也一样:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs"><span>nav</span>, <span>aside</span> &#123;  <span>a</span> &#123;<span>color</span><span>: blue&#125;&#125;</span></code></pre><p>首先<code>sass</code>将<code>nav</code>和<code>a</code><code>aside</code>和<code>a</code>分别组合，然后将二者重新组合成一个群组选择器:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">nav</span></span> <span><span class="hljs-selector-tag">a</span></span>, <span><span class="hljs-selector-tag">aside</span></span> <span><span class="hljs-selector-tag">a</span></span> <span>&#123;<span><span><span class="hljs-attribute">color</span></span>:<span> blue</span></span></span>&#125;</code></pre><p>处理这种群组选择器规则嵌套上的强大能力，正是<code>sass</code>在减少重复敲写方面的贡献之一。尤其在当嵌套级别达到两层甚至三层以上时，与普通的<code>css</code>编写方式相比，只写一遍群组选择器大大减少了工作量。</p><p>有利必有弊，你需要特别注意群组选择器的规则嵌套生成的<code>css</code>。虽然<code>sass</code>让你的样式表看上去很小，但实际生成的<code>css</code>却可能非常大，这会降低网站的速度。</p><p>关于选择器嵌套的最后一个方面，我们看看<code>sass</code>如何处理组合选择器，比如&gt;、+和~的使用。你将看到，这种场景下你甚至无需使用父选择器标识符。</p></div><div style="clear:both"></div></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于Sass变量名用中划线还是下划线分隔问题</title>
      <link href="front/sass/sass-name-style/"/>
      <url>front/sass/sass-name-style/</url>
      
        <content type="html"><![CDATA[<h3 id="开门见山"><a href="#开门见山" class="headerlink" title="开门见山"></a>开门见山</h3><p><strong>这个问题说白了就是你爱用啥用啥,都通用的</strong></p><div class="content-intro view-box "><p></p><p><code>sass</code>的变量名可以与<code>css</code>中的属性名和选择器名称相同，包括中划线和下划线。这完全取决于个人的喜好，有些人喜欢使用中划线来分隔变量中的多个词(如<code>$highlight-color</code>)，而有些人喜欢使用下划线(如<code>$highlight_color</code>)。使用中划线的方式更为普遍，这也是<code>compass</code>和本文都用的方式。</p><p>不过，<code>sass</code>并不想强迫任何人一定使用中划线或下划线，所以这两种用法相互兼容。用中划线声明的变量可以使用下划线的方式引用，反之亦然。这意味着即使<code>compass</code>选择用中划线的命名方式，这并不影响你在使用<code>compass</code>的样式中用下划线的命名方式进行引用:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs php"><span>$link-color</span><span>: blue;</span><span>a</span> &#123;  <span>color</span><span>: <span>$link_color</span>;</span>&#125;<p><span><span class="hljs-comment">//编译后</span></span></p><p><span>a</span> &#123;<br>  <span>color</span><span>: blue;</span><br>&#125;</code></pre><p>在上例中，<code>$link-color</code>和<code>$link_color</code>其实指向的是同一个变量。实际上，在<code>sass</code>的大多数地方，中划线命名的内容和下划线命名的内容是互通的，除了变量，也包括对混合器和Sass函数的命名。但是在<code>sass</code>中纯<code>css</code>部分不互通，比如类名、ID或属性名。</p><p>尽管变量自身提供了很多有用的地方，但是<code>sass</code>基于变量提供的更为强大的工具才是我们关注的焦点。只有当变量与<code>sass</code>的其他特性一起使用时，才能发挥其全部的潜能。接下来，我们将探讨其中一个非常重要的特性，即规则嵌套。</p><br></div></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sass中嵌套属性</title>
      <link href="front/sass/sass-nested%20attribute/"/>
      <url>front/sass/sass-nested%20attribute/</url>
      
        <content type="html"><![CDATA[<h3 id="启航"><a href="#启航" class="headerlink" title="启航"></a>启航</h3><div class="content-intro view-box "><p></p><p>在<code>sass</code>中，除了CSS选择器，属性也可以进行嵌套。尽管编写属性涉及的重复不像编写选择器那么糟糕，但是要反复写<code>border-style</code><code>border-width</code><code>border-color</code>以及<code>border-*</code>等也是非常烦人的。在<code>sass</code>中，你只需敲写一遍<code>border</code>:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">nav</span></span> &#123;  <span><span class="hljs-attribute">border</span></span><span>: &#123;  style: solid;</span>  <span><span class="hljs-attribute">width</span></span><span>: <span><span class="hljs-number">1px</span></span>;</span>  <span><span class="hljs-attribute">color</span></span><span>: <span><span class="hljs-number">#ccc</span></span>;</span>  &#125;&#125;</code></pre><p>嵌套属性的规则是这样的:把属性名从中划线-的地方断开，在根属性后边添加一个冒号:，紧跟一个<code>&#123; &#125;</code>块，把子属性部分写在这个<code>&#123; &#125;</code>块中。就像<code>css</code>选择器嵌套一样，<code>sass</code>会把你的子属性一一解开，把根属性和子属性部分通过中划线-连接起来，最后生成的效果与你手动一遍遍写的<code>css</code>样式一样:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">nav</span></span> <span>&#123;  <span><span><span class="hljs-attribute">border-style</span></span>:<span> solid</span></span>;  <span><span><span class="hljs-attribute">border-width</span></span>:<span> <span><span class="hljs-number">1px</span></span></span></span>;  <span><span><span class="hljs-attribute">border-color</span></span>:<span> <span><span class="hljs-number">#ccc</span></span></span></span>;<span>&#125;</span></span></code></pre><p>对于属性的缩写形式，你甚至可以像下边这样来嵌套，指明例外规则:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">nav</span></span> &#123;  <span><span class="hljs-attribute">border</span></span><span>: <span><span class="hljs-number">1px</span></span> solid <span><span class="hljs-number">#ccc</span></span> &#123;  left: <span><span class="hljs-number">0px</span></span>;</span>  <span><span class="hljs-attribute">right</span></span><span>: <span><span class="hljs-number">0px</span></span>;</span>  &#125;&#125;</code></pre><p>这比下边这种同等样式的写法要好:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">nav</span></span> <span>&#123;  <span><span><span class="hljs-attribute">border</span></span>:<span> <span><span class="hljs-number">1px</span></span> solid <span><span class="hljs-number">#ccc</span></span></span></span>;  <span><span><span class="hljs-attribute">border-left</span></span>:<span> <span><span class="hljs-number">0px</span></span></span></span>;  <span><span><span class="hljs-attribute">border-right</span></span>:<span> <span><span class="hljs-number">0px</span></span></span></span>;<span>&#125;</span></span></code></pre><p>属性和选择器嵌套是非常伟大的特性，因为它们不仅大大减少了你的编写量，而且通过视觉上的缩进使你编写的样式结构更加清晰，更易于阅读和开发。</p><p>即便如此，随着你的样式表变得越来越大，这种写法也很难保持结构清晰。有时，处理这种大量样式的唯一方法就是把它们分拆到多个文件中。<code>sass</code>通过对<code>css</code>原有<code>@import</code>规则的改进直接支持了这一特性。</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sass中嵌套CSS的规则</title>
      <link href="front/sass/sass-nesting-css-rule/"/>
      <url>front/sass/sass-nesting-css-rule/</url>
      
        <content type="html"><![CDATA[<h3 id="启航"><a href="#启航" class="headerlink" title="启航"></a>启航</h3><div class="content-intro view-box "><p></p><p><code>css</code>中重复写选择器是非常恼人的。如果要写一大串指向页面中同一块的样式时，往往需要一遍又一遍地写同一个<code>ID</code>:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">h1</span></span> <span>&#123; <span><span><span class="hljs-attribute">color</span></span>:<span> <span><span class="hljs-number">#333</span></span> </span></span></span>&#125;<span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">p</span></span> <span>&#123; <span><span><span class="hljs-attribute">margin-bottom</span></span>:<span> <span><span class="hljs-number">1.4em</span></span> </span></span></span>&#125;<span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">aside</span></span> <span>&#123; <span><span><span class="hljs-attribute">background-color</span></span>:<span> <span><span class="hljs-number">#EEE</span></span> </span></span></span>&#125;</code></pre><p>像这种情况，<code>sass</code>可以让你只写一遍，且使样式可读性更高。在Sass中，你可以像俄罗斯套娃那样在规则块中嵌套规则块。<code>sass</code>在输出<code>css</code>时会帮你把这些嵌套规则处理好，避免你的重复书写。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs bash"><span><span class="hljs-comment">#content</span></span><span class="hljs-comment"> &#123;</span>  <span>article</span> &#123;    <span>h1</span> &#123; <span>color</span><span>: <span><span class="hljs-comment">#333</span></span><span class="hljs-comment"> &#125;</span>    </span><span><span>p</span></span><span> &#123; </span><span><span>margin-bottom</span></span><span>: <span>1.4em</span> &#125;  &#125;  </span><span><span>aside</span></span><span> &#123; </span><span><span>background-color</span></span><span>: <span><span class="hljs-comment">#EEE</span></span><span class="hljs-comment"> &#125;</span>&#125;</span></code></pre><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"> <span><span class="hljs-comment">/* 编译后 */</span></span><span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">h1</span></span> <span>&#123; <span><span><span class="hljs-attribute">color</span></span>:<span> <span><span class="hljs-number">#333</span></span> </span></span></span>&#125;<span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">p</span></span> <span>&#123; <span><span><span class="hljs-attribute">margin-bottom</span></span>:<span> <span><span class="hljs-number">1.4em</span></span> </span></span></span>&#125;<span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">aside</span></span> <span>&#123; <span><span><span class="hljs-attribute">background-color</span></span>:<span> <span><span class="hljs-number">#EEE</span></span> </span></span></span>&#125;</code></pre><p>上边的例子，会在输出<code>css</code>时把它转换成跟你之前看到的一样的效果。这个过程中，<code>sass</code>用了两步，每一步都是像打开俄罗斯套娃那样把里边的嵌套规则块一个个打开。首先，把<code>#content</code>(父级)这个<code>id</code>放到<code>article</code>选择器(子级)和<code>aside</code>选择器(子级)的前边:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs bash"><span><span class="hljs-comment">#content</span></span><span class="hljs-comment"> &#123;</span>  <span>article</span> &#123;    <span>h1</span> &#123; <span>color</span><span>: <span><span class="hljs-comment">#333</span></span><span class="hljs-comment"> &#125;</span>    </span><span><span>p</span></span><span> &#123; </span><span><span>margin-bottom</span></span><span>: <span>1.4em</span> &#125;  &#125;  </span><span><span><span><span class="hljs-comment">#c</span></span><span class="hljs-comment">ontent</span></span></span><span><span class="hljs-comment"> </span></span><span><span><span class="hljs-comment">aside</span></span></span><span><span class="hljs-comment"> &#123; </span></span><span><span><span class="hljs-comment">background-color</span></span></span><span><span class="hljs-comment">: </span><span><span class="hljs-comment">#EEE</span></span><span class="hljs-comment"> &#125;</span>&#125;</span></code></pre><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"> <span><span class="hljs-comment">/* 编译后 */</span></span><span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">h1</span></span> <span>&#123; <span><span><span class="hljs-attribute">color</span></span>:<span> <span><span class="hljs-number">#333</span></span> </span></span></span>&#125;<span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">p</span></span> <span>&#123; <span><span><span class="hljs-attribute">margin-bottom</span></span>:<span> <span><span class="hljs-number">1.4em</span></span> </span></span></span>&#125;<span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">aside</span></span> <span>&#123; <span><span><span class="hljs-attribute">background-color</span></span>:<span> <span><span class="hljs-number">#EEE</span></span> </span></span></span>&#125;</code></pre><p>然后，<code>#content article</code>里边还有嵌套的规则，<code>sass</code>重复一遍上边的步骤，把新的选择器添加到内嵌的选择器前边。</p><p>一个给定的规则块，既可以像普通的CSS那样包含属性，又可以嵌套其他规则块。当你同时要为一个容器元素及其子元素编写特定样式时，这种能力就非常有用了。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs bash"><span><span class="hljs-comment">#content</span></span><span class="hljs-comment"> &#123;</span>  <span>background-color</span><span>: <span><span class="hljs-comment">#f5f5f5</span></span><span class="hljs-comment">;</span></span>  <span>aside</span> &#123; <span>background-color</span><span>: <span><span class="hljs-comment">#eee</span></span><span class="hljs-comment"> &#125;</span>&#125;</span></code></pre><p>容器元素的样式规则会被单独抽离出来，而嵌套元素的样式规则会像容器元素没有包含任何属性时那样被抽离出来。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-id">#content</span></span> <span>&#123; <span><span><span class="hljs-attribute">background-color</span></span>:<span> <span><span class="hljs-number">#f5f5f5</span></span> </span></span></span>&#125;<span><span class="hljs-selector-id">#content</span></span> <span><span class="hljs-selector-tag">aside</span></span> <span>&#123; <span><span><span class="hljs-attribute">background-color</span></span>:<span> <span><span class="hljs-number">#eee</span></span> </span></span></span>&#125;</code></pre><p>大多数情况下这种简单的嵌套都没问题，但是有些场景下不行，比如你想要在嵌套的选择器里边立刻应用一个类似于<code>:hover</code>的伪类。为了解决这种以及其他情况，<code>sass</code>提供了一个特殊结构<code>&amp;</code>。</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> css </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sass中子组合选择器和同层组合选择器：&gt;、+和~</title>
      <link href="front/sass/sass-son-brother-select/"/>
      <url>front/sass/sass-son-brother-select/</url>
      
        <content type="html"><![CDATA[<h3 id="启航"><a href="#启航" class="headerlink" title="启航"></a>启航</h3><div class="content-intro view-box "><p></p><p>上边这三个组合选择器必须和其他选择器配合使用，以指定浏览器仅选择某种特定上下文中的元素。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">section</span></span> <span>&#123; <span><span><span class="hljs-attribute">margin</span></span>:<span> <span><span class="hljs-number">5px</span></span> </span></span></span>&#125;<span><span class="hljs-selector-tag">article</span></span> &gt; <span><span class="hljs-selector-tag">section</span></span> <span>&#123; <span><span><span class="hljs-attribute">border</span></span>:<span> <span><span class="hljs-number">1px</span></span> solid <span><span class="hljs-number">#ccc</span></span> </span></span></span>&#125;</code></pre><p>你可以用子组合选择器&gt;选择一个元素的直接子元素。上例中，第一个选择器会选择article下的所有命中section选择器的元素。第二个选择器只会选择article下紧跟着的子元素中命中section选择器的元素。</p><p>在下例中，你可以用同层相邻组合选择器<code>+</code>选择<code>header</code>元素后紧跟的<code>p</code>元素:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">header</span></span> + <span><span class="hljs-selector-tag">p</span></span> <span>&#123; <span><span><span class="hljs-attribute">font-size</span></span>:<span> <span><span class="hljs-number">1.1em</span></span> </span></span></span>&#125;</code></pre><p>你也可以用同层全体组合选择器<code>~</code>，选择所有跟在<code>article</code>后的同层<code>article</code>元素，不管它们之间隔了多少其他元素:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">article</span></span> ~ <span><span class="hljs-selector-tag">article</span></span> <span>&#123; <span><span><span class="hljs-attribute">border-top</span></span>:<span> <span><span class="hljs-number">1px</span></span> dashed <span><span class="hljs-number">#ccc</span></span> </span></span></span>&#125;</code></pre><p>这些组合选择器可以毫不费力地应用到<code>sass</code>的规则嵌套中。可以把它们放在外层选择器后边，或里层选择器前边:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs bash"><span>article</span> &#123;  ~ <span>article</span> &#123; <span>border-top</span><span>: <span>1px</span> dashed <span><span class="hljs-comment">#ccc</span></span><span class="hljs-comment"> &#125;</span>  &gt; </span><span><span>section</span></span><span> &#123; </span><span><span>background</span></span><span>: <span><span class="hljs-comment">#eee</span></span><span class="hljs-comment"> &#125;</span>  </span><span><span>dl</span></span><span> &gt; &#123;    </span><span><span>dt</span></span><span> &#123; </span><span><span>color</span></span><span>: <span><span class="hljs-comment">#333</span></span><span class="hljs-comment"> &#125;</span>    </span><span><span>dd</span></span><span> &#123; </span><span><span>color</span></span><span>: <span><span class="hljs-comment">#555</span></span><span class="hljs-comment"> &#125;</span>  &#125;  </span><span><span>nav</span></span><span> + &amp; &#123; </span><span><span>margin-top</span></span><span>: <span>0</span> &#125;&#125;</span></code></pre><p><code>sass</code>会如你所愿地将这些嵌套规则一一解开组合在一起:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs css"><span><span class="hljs-selector-tag">article</span></span> ~ <span><span class="hljs-selector-tag">article</span></span> <span>&#123; <span><span><span class="hljs-attribute">border-top</span></span>:<span> <span><span class="hljs-number">1px</span></span> dashed <span><span class="hljs-number">#ccc</span></span> </span></span></span>&#125;<span><span class="hljs-selector-tag">article</span></span> &gt; <span><span class="hljs-selector-tag">footer</span></span> <span>&#123; <span><span><span class="hljs-attribute">background</span></span>:<span> <span><span class="hljs-number">#eee</span></span> </span></span></span>&#125;<span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">dl</span></span> &gt; <span><span class="hljs-selector-tag">dt</span></span> <span>&#123; <span><span><span class="hljs-attribute">color</span></span>:<span> <span><span class="hljs-number">#333</span></span> </span></span></span>&#125;<span><span class="hljs-selector-tag">article</span></span> <span><span class="hljs-selector-tag">dl</span></span> &gt; <span><span class="hljs-selector-tag">dd</span></span> <span>&#123; <span><span><span class="hljs-attribute">color</span></span>:<span> <span><span class="hljs-number">#555</span></span> </span></span></span>&#125;<span><span class="hljs-selector-tag">nav</span></span> + <span><span class="hljs-selector-tag">article</span></span> <span>&#123; <span><span><span class="hljs-attribute">margin-top</span></span>:<span> <span><span class="hljs-number">0</span></span> </span></span></span>&#125;</code></pre><p>在<code>sass</code>中，不仅仅<code>css</code>规则可以嵌套，对属性进行嵌套也可以减少很多重复性的工作。</p></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sass中变量声明</title>
      <link href="front/sass/sass-var-declare/"/>
      <url>front/sass/sass-var-declare/</url>
      
        <content type="html"><![CDATA[<h3 id="启航"><a href="#启航" class="headerlink" title="启航"></a>启航</h3><div class="content-intro view-box "><p></p><p><code>sass</code>变量的声明和<code>css</code>属性的声明很像:</p>              <pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs bash"><span><span class="hljs-variable"><span class="hljs-variable">$highlight</span></span>-color</span><span>: <span><span class="hljs-comment"><span class="hljs-comment">#F90</span></span></span><span class="hljs-comment"><span class="hljs-comment">;</span></span></span></code></pre>              <p>这意味着变量<code>$highlight-color</code>现在的值是<code>#F90</code>。任何可以用作<code>css</code>属性值的赋值都可以用作<code>sass</code>的变量值，甚至是以空格分割的多个属性值，如<code>$basic-border: 1px solidblack;</code>，或以逗号分割的多个属性值，如<code>$plain-font: "Myriad Pro"、Myriad、"HelveticaNeue"、Helvetica、"Liberation Sans"、Arial和sans-serif; sans-serif;</code>。这时变量还没有生效，除非你引用这个变量——我们很快就会了解如何引用。</p><p>与<code>CSS</code>属性不同，变量可以在<code>css</code>规则块定义之外存在。当变量定义在<code>css</code>规则块内，那么该变量只能在此规则块内使用。如果它们出现在任何形式的<code>&#123;...&#125;</code>块中(如<code>@media</code>或者<code>@font-face</code>块)，情况也是如此:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs php"><span>$nav-color</span><span>: <span><span class="hljs-comment"><span class="hljs-comment">#F90</span></span></span><span class="hljs-comment"><span class="hljs-comment">;</span></span></span><span>nav</span> &#123;  <span>$width</span><span>: <span><span class="hljs-number"><span class="hljs-number">100</span></span>px</span>;</span>  <span>width</span><span>: <span>$width</span>;</span>  <span>color</span><span>: <span>$nav-color</span>;</span>&#125;<p><span><span class="hljs-comment"><span class="hljs-comment">//编译后</span></span></span></p><p><span>nav</span> &#123;<br>  <span>width</span><span>: <span><span class="hljs-number"><span class="hljs-number">100</span></span>px</span>;</span><br>  <span>color</span><span>: <span><span class="hljs-comment"><span class="hljs-comment">#F90</span></span></span><span class="hljs-comment"><span class="hljs-comment">;</span></span></span><br>&#125;<br></code></pre><p>在这段代码中，<code>$nav-color</code>这个变量定义在了规则块外边，所以在这个样式表中都可以像<code>nav</code>规则块那样引用它。<code>$width</code>这个变量定义在了<code>nav</code>的<code>&#123; &#125;</code>规则块内，所以它只能在<code>nav</code>规则块内使用。这意味着是你可以在样式表的其他地方定义和使用<code>$width</code>变量，不会对这里造成影响。</p><p>只声明变量其实没啥用处，我们最终的目的还是使用它们。上例已介绍了如何使用<code>$nav-color</code>和<code>$width</code>这两个变量，接下来我们将进一步探讨变量的使用方法。</p><br></div></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sass中变量的引用</title>
      <link href="front/sass/sass-var-reference/"/>
      <url>front/sass/sass-var-reference/</url>
      
        <content type="html"><![CDATA[<h3 id="启航"><a href="#启航" class="headerlink" title="启航"></a>启航</h3><div class="content-intro view-box "><p></p><p>凡是<code>css</code>属性的标准值(比如说1px或者bold)可存在的地方，变量就可以使用。<code>css</code>生成时，变量会被它们的值所替代。之后，如果你需要一个不同的值，只需要改变这个变量的值，则所有引用此变量的地方生成的值都会随之改变。</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs php"><span>$highlight-color</span><span>: <span><span class="hljs-comment">#F90</span></span><span class="hljs-comment">;</span></span><span>.selected</span> &#123;  <span>border</span><span>: <span><span class="hljs-number">1</span>px</span> solid <span>$highlight-color</span>;</span>&#125;<p><span><span class="hljs-comment">//编译后</span></span></p><p><span>.selected</span> &#123;<br>  <span>border</span><span>: <span><span class="hljs-number">1</span>px</span> solid <span><span class="hljs-comment">#F90</span></span><span class="hljs-comment">;</span></span><br>&#125;<br></code></pre><p>看上边示例中的<code>$highlight-color</code>变量，它被直接赋值给<code>border</code>属性，当这段代码被编译输出<code>css</code>时，<code>$highlight-color</code>会被<code>#F90</code>这一颜色值所替代。产生的效果就是给<code>selected</code>这个类一条1像素宽、实心且颜色值为<code>#F90</code>的边框。</p><p>在声明变量时，变量值也可以引用其他变量。当你通过粒度区分，为不同的值取不同名字时，这相当有用。下例在独立的颜色值粒度上定义了一个变量，且在另一个更复杂的边框值粒度上也定义了一个变量:</p><pre><a class="code-copy right0" title="复制到剪切板"><i class="icon-copy"></i></a><code class="hljs php"><span>$highlight-color</span><span>: <span><span class="hljs-comment">#F90</span></span><span class="hljs-comment">;</span></span><br><span>$highlight-border</span><span>: <span><span class="hljs-number">1</span>px</span> solid <span>$highlight-color</span>;</span><br><span>.selected</span> &#123;<br>  <span>border</span><span>: <span>$highlight-border</span>;</span><br>&#125;</p><p><span><span class="hljs-comment">//编译后</span></span></p><p><span>.selected</span> &#123;<br>  <span>border</span><span>: <span><span class="hljs-number">1</span>px</span> solid <span><span class="hljs-comment">#F90</span></span><span class="hljs-comment">;</span></span><br>&#125;</code></pre><p>这里，<code>$highlight-border</code>变量的声明中使用了<code>$highlight-color</code>这个变量。产生的效果就跟你直接为<code>border</code>属性设置了一个<code>1px</code> <code>$highlight-color solid</code>的值是一样的。最后，我们来了解一下变量命名的实用技巧，以结束关于变量的介绍。</p><br></div></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sass </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>快速部署Bootstrap环境</title>
      <link href="front/bootstrap/bootstrap-cdn/"/>
      <url>front/bootstrap/bootstrap-cdn/</url>
      
        <content type="html"><![CDATA[<h3 id="快速部署"><a href="#快速部署" class="headerlink" title="快速部署"></a>快速部署</h3><p>使用 Bootstrap CDN嵌入4行代码就能完成导入！ </p><h3 id="步骤一-1行-CSS"><a href="#步骤一-1行-CSS" class="headerlink" title="步骤一:1行 CSS"></a>步骤一:1行 CSS</h3><p>复制下面的 <link> 样式表粘贴到网页 <head> 里面，并放在其它CSS文件之前.</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css&quot;</span> <span class="attr">integrity</span>=<span class="string">&quot;sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T&quot;</span> <span class="attr">crossorigin</span>=<span class="string">&quot;anonymous&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="步骤二-3行-JS"><a href="#步骤二-3行-JS" class="headerlink" title="步骤二:3行 JS"></a>步骤二:3行 JS</h3><p>全局组件运行在 jQuery 组件上，其中包括 Popper.js, 以及系统内置 JavaScript 插件. 建议将 <code>&lt;script&gt;</code> 的结束放在页面的 <code>&lt;/body&gt;</code> 之前以符合新移动WEB规范，并遵循下面代码的先后顺序。</p><p>您可以引用 jQuery 精简版,兼容完整版，并无二异。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://code.jquery.com/jquery-3.3.1.slim.min.js&quot;</span> <span class="attr">integrity</span>=<span class="string">&quot;sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo&quot;</span> <span class="attr">crossorigin</span>=<span class="string">&quot;anonymous&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js&quot;</span> <span class="attr">integrity</span>=<span class="string">&quot;sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1&quot;</span> <span class="attr">crossorigin</span>=<span class="string">&quot;anonymous&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js&quot;</span> <span class="attr">integrity</span>=<span class="string">&quot;sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM&quot;</span> <span class="attr">crossorigin</span>=<span class="string">&quot;anonymous&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这里列出了需要JQuery、Bootstrap.js、Popper.js组件清单，如果你不熟悉组件可以继续查看本文档的其它部份的示例源码。</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> Bootstrap </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Sublime运行代码</title>
      <link href="ide/sublime/sublime-openinbrowser/"/>
      <url>ide/sublime/sublime-openinbrowser/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>很多小伙伴使用sublime写前端html文件,但是在浏览器打开时,可能会遇到一些问题</p><p>比如,不能点击open in browser 实现在浏览器中打开</p><p>今天小编就教大家安装一个插件,实现快捷键在浏览器中打开刚编写的html文件</p><h3 id="安装view-in-browser插件"><a href="#安装view-in-browser插件" class="headerlink" title="安装view in browser插件"></a>安装view in browser插件</h3><p>首先,直接就打开软件&gt;</p><p>按快捷键 <code>ctrl+shift+P</code></p><h3 id="选择Package-Control"><a href="#选择Package-Control" class="headerlink" title="选择Package Control"></a>选择<code>Package Control</code></h3><p>然后再搜索框输入：pcip</p><p>此时我们看见了第一个首选的插件Package Control:Install Package，我们直接回车就好，稍等片刻会再次出现一个搜索框，</p><h3 id="安装View-In-Browser插件"><a href="#安装View-In-Browser插件" class="headerlink" title="安装View In Browser插件"></a>安装View In Browser插件</h3><p>输入:view,没有安装的朋友此时框框第一个插件会是[View In Browser],</p><p>直接回车即可，如果已经安装了View In Browser插件的会像我一样没有展示那个插件。</p><h3 id="设置运行代码快捷键"><a href="#设置运行代码快捷键" class="headerlink" title="设置运行代码快捷键"></a>设置运行代码快捷键</h3><p>上面我们安装好了view in browser插件，接下来我们开始设置快捷键。</p><p>设置的快捷键是”ctrl+shift+b”</p><p>点击Preferences &gt; key Bindings </p><h3 id="然后在右边空白框的”-”括号中间内输入："><a href="#然后在右边空白框的”-”括号中间内输入：" class="headerlink" title="然后在右边空白框的”[]”括号中间内输入："></a>然后在右边空白框的”[]”括号中间内输入：</h3><p> { “keys”: [“ctrl+shift+b”], “command”: “open_in_browser” },</p><p>然后ctrl+s保存关闭窗口。</p><h3 id="最最最关键的一步了"><a href="#最最最关键的一步了" class="headerlink" title="最最最关键的一步了"></a>最最最关键的一步了</h3><p>设置html文件默认的打开方式为chrome</p><p>然后就成了</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> sublime </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>我的第一个Vue程序</title>
      <link href="front/vue/old/vue-helloworld/"/>
      <url>front/vue/old/vue-helloworld/</url>
      
        <content type="html"><![CDATA[<h3 id="废话不多讲-直接就上代码"><a href="#废话不多讲-直接就上代码" class="headerlink" title="废话不多讲,直接就上代码"></a>废话不多讲,直接就上代码</h3><h3 id="index-html"><a href="#index-html" class="headerlink" title="index.html"></a>index.html</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">title</span>&gt;</span>VueJS Tutorials<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">&quot;styles.css&quot;</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/vue&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;vue-app&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">h1</span>&gt;</span>&#123;&#123; greet(&#x27;afternoon&#x27;) &#125;&#125;<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>Name: &#123;&#123; name&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>Job: &#123;&#123; job &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;app.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="app-js"><a href="#app-js" class="headerlink" title="app.js"></a>app.js</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">    el: <span class="string">&#x27;#vue-app&#x27;</span>,</span><br><span class="line">    data: &#123;</span><br><span class="line">        name: <span class="string">&#x27;Shaun&#x27;</span>,</span><br><span class="line">        job: <span class="string">&#x27;Ninja&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    methods: &#123;</span><br><span class="line">        greet: <span class="function"><span class="keyword">function</span>(<span class="params">time</span>)</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&#x27;Good &#x27;</span> + time + <span class="string">&#x27;, &#x27;</span> + <span class="built_in">this</span>.name;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="Vue对象中的属性"><a href="#Vue对象中的属性" class="headerlink" title="Vue对象中的属性"></a>Vue对象中的属性</h3><ul><li>el: element 需要获取的元素,一定是html中的跟容器元素  </li><li>data: 用于数据的存储  </li><li>methods: 用于存储各种方法  </li><li>data-binding :给属性绑定对应的值  </li><li>computed: 计算属性,这个性能好,不是全部触发  <ul><li>操作虚拟dom 比较不同的地方,要是有才触发你这个方法  </li><li>只有大量的耗时才使用这个computed属性,比如说搜索  </li></ul></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jetbrains 系列IDE 使用技巧</title>
      <link href="ide/jetbrains/idea/Intellij-IDEA/"/>
      <url>ide/jetbrains/idea/Intellij-IDEA/</url>
      
        <content type="html"><![CDATA[<p><a href="http://mp.weixin.qq.com/s?__biz=MzIzMzgxOTQ5NA==&mid=2247485196&idx=1&sn=9160d260e7f4cf5941f27c884a62e8e5&chksm=e8fe9b05df891213e2ce2b46824f7c67cac7e5be10e84aa8102e9c65edec5cc40a40550ac9a7&scene=21#wechat_redirect">谈谈我与 Intellij IDEA 的故事</a>  </p><p><a href="https://mp.weixin.qq.com/s/MH0pYF2vAzYZ-IfnIBROpQ">Intellij IDEA 中我一直在用的几个插件</a>  </p><h3 id="下面是官方快捷键"><a href="#下面是官方快捷键" class="headerlink" title="下面是官方快捷键"></a>下面是官方快捷键</h3><h3 id="Editing"><a href="#Editing" class="headerlink" title="Editing"></a>Editing</h3><p>Ctrl + Space Basic code completion<br>Alt + Enter Show intention actions and quick-fixes<br>Ctrl + P Parameter info (within method call arguments)<br>Ctrl + Q Quick documentation lookup<br>Ctrl + mouse over code Brief Info<br>Ctrl + F1 Show descriptions of error or warning at caret<br>Alt + Insert Generate code…<br>Ctrl + Alt + T Surround with…(if..else, try..catch, for, etc.)<br>Ctrl + J Insert Live template<br>Ctrl + / Comment/uncomment with line comment<br>Ctrl + Shift + / Comment/uncomment with block comment<br>Ctrl + W Select successively increasing code blocks<br>Ctrl + Shift + W Decrease current selection to previous state<br>Alt+Q Context Info<br>Ctrl + Alt + L Reformat code<br>Ctrl + Alt + I Auto-indent line(s)  </p><p>Tab Indent selected lines<br>Shift + Tab Unindent selected lines<br>Ctrl + Shift + V Paste from recent buffers…<br>Ctrl + D Duplicate current line or selected block<br>Ctrl + Y Delete line at caret<br>Alt + Shift + Up Move line up<br>Alt + Shift + Down Move line down<br>Ctrl + Shift + J Join lines<br>Ctrl + Enter Split lines<br>Shift + Enter Start new line<br>Ctrl + Shift + U Toggle case for word at caret or selected   </p><p>Ctrl + Shift + ] Select till code block end<br>Ctrl + Shift + [ Select till code block start<br>Ctrl + Delete Delete to word end<br>Ctrl + Backspace Delete to word start<br>Ctrl + NumPad+ Expand code block<br>Ctrl + NumPad- Collapse code block<br>Ctrl + Shift + NumPad+ Expand all<br>Ctrl + Shift + NumPad- Collapse all<br>Ctrl + F4 Close active editor tab  </p><h3 id="Multiple-carets-and-selections"><a href="#Multiple-carets-and-selections" class="headerlink" title="Multiple carets and selections"></a>Multiple carets and selections</h3><p>Alt + Click Add or remove caret<br>Shift + Ctrl + Alt + J Select all occurrences<br>Alt + J Select next occurrence<br>Alt + Shift + J Unselect occurrence<br>Esc Unselect all occurrences or carets jetbrains.com/webstorm blog.jetbrains.com/webstorm @WebStormI  </p><h3 id="Running"><a href="#Running" class="headerlink" title="Running"></a>Running</h3><p>Alt + Shift + F10 Select configuration and run<br>Alt + Shift + F9 Select configuration and debug<br>Shift + F10 Run<br>Shift + F9 Debug<br>Ctrl + Shift + F10 Run context configuration from editor<br>Alt + Shift + R Rerun tests<br>Alt + F11 Run Gulp/Grunt/npm tasks  </p><h3 id="Debugging"><a href="#Debugging" class="headerlink" title="Debugging"></a>Debugging</h3><p>F8 Step over<br>F7 Step into<br>Shift + F7 Smart step into<br>Shift + F8 Step out<br>Alt + F9 Run to cursor<br>Alt + F8 Evaluate expression<br>F9 Resume program<br>Ctrl + F8 Toggle breakpoint<br>Ctrl + Shift + F8 View breakpoints  </p><h3 id="Navigation"><a href="#Navigation" class="headerlink" title="Navigation"></a>Navigation</h3><p>Ctrl + B , Ctrl + Click Go to declaration<br>Ctrl + N Go to class<br>Ctrl + Shift + N Go to file<br>Ctrl + Alt + Shift + N Go to symbol<br>Alt + Right Go to next editor tab<br>Alt + Left Go to previous editor tab<br>F12 Go back to previous tool window<br>Esc Go to editor (from tool window)<br>Ctrl + G Go to line<br>Ctrl + E Recent files popup<br>Ctrl + Alt + Right Navigate forward<br>Ctrl + Alt + Left Navigate back<br>Ctrl + Shift + Backspace Navigate to last edit location<br>Alt + F1 Select current file or symbol in any view<br>Ctrl + Alt + B Go to implementation(s)<br>Ctrl + Shift + I Open quick definition lookup<br>Ctrl + Shift + B Go to type declaration<br>Ctrl + U Go to super-method/super-class<br>Alt + Up Go to previous method<br>Alt + Down Go to next method<br>Ctrl + ] / [ Move to code block end/start<br>Cltrl + Shift + M Move caret to matching brace<br>Ctrl + F12 File structure popup<br>Ctrl + H Type hierarchy<br>Ctrl + Alt + H Call hierarchy<br>F2 / Shift + F2 Next/previous highlighted error<br>F4 , Ctrl + Enter Jump to source<br>Alt + Home Jump to navigation bar<br>F11 Toggle bookmark<br>Ctrl + Shift + F11 Toggle bookmark with mnemonic<br>Ctrl + #[0-9] Go to numbered bookmark<br>Shift + F11 Show bookmarks<br>DEFAULT WINDOWS &amp; LINUX KEYMAP<br>To find any action inside the IDE use Find Action (Ctrl + Shift + A)   </p><h3 id="Search-Replace"><a href="#Search-Replace" class="headerlink" title="Search/Replace"></a>Search/Replace</h3><p>Ctrl + F Find<br>F3 Find next<br>Shift + F3 Find previous<br>Ctrl + Shift + F Find in path<br>Ctrl + R Replace<br>Ctrl + Shift + R Replace in path  </p><h3 id="Usage-Search"><a href="#Usage-Search" class="headerlink" title="Usage Search"></a>Usage Search</h3><p>Alt + F7 Find usages<br>Ctrl + F7 Find usages in file<br>Ctrl + Shift + F7 Highlight usages in file<br>Ctrl + Alt + F7 Show usages  </p><h3 id="Refactoring"><a href="#Refactoring" class="headerlink" title="Refactoring"></a>Refactoring</h3><p>Ctrl + Alt + Shift +T Refactor this<br>F5 / F6 Copy / Move<br>Alt + Delete Safe Delete<br>Shift + F6 Rename<br>Ctrl + F6 Change function signature<br>Ctrl + Alt + N Inline Variable<br>Ctrl + Alt + M Extract Method<br>Ctrl + Alt + V Extract Variable<br>Ctrl + Alt + C Extract Constant<br>Ctrl + Alt + P Extract Parameter  </p><h3 id="VCS-Local-History"><a href="#VCS-Local-History" class="headerlink" title="VCS/Local History"></a>VCS/Local History</h3><p>Alt + BackQuote (`) ‘VCS’ quick popup<br>Ctrl + K Commit project to VCS<br>Ctrl + T Update project from VCS<br>Alt + Shift + C View recent changes  </p><h3 id="General"><a href="#General" class="headerlink" title="General"></a>General</h3><p>Double Shift Search everywhere<br>Ctrl + Shift + A Find Action<br>Alt + #[0-9] Open corresponding tool window<br>Ctrl + Shift + F12 Toggle maximizing editor<br>Alt + Shift + F Add to Favorites<br>Alt + Shift + I Inspect current file with current profile<br>Ctrl + BackQuote (`) Quick switch current scheme<br>Ctrl + Alt + S Open Settings dialog<br>Ctrl + Tab Switch between tabs and tool window   </p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> idea </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>教你将Visual Studio Code打造成更加强大的sublime</title>
      <link href="ide/vscode-change-sublime-theme/"/>
      <url>ide/vscode-change-sublime-theme/</url>
      
        <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言:"></a>前言:</h3><p>相信很多学习编程的小伙伴都用过sublime编辑器吧,它是一个很小巧并且功能强大的编辑器<br>但是如果有一天你需要使用vscode,可能你很不适应它的一些习惯<br>今天小编就教大家将Visual Studio Code打造成sublime的颜色主题  </p><h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>快捷键对于编辑器就相当于八倍镜对于98K  </p><ul><li>别管别的,在vscode任意界面,直接就按<code>ctrl+shift+P</code>打开命令面板</li></ul><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/vscode_ctrl_shift_p.png" alt="img"></p><ul><li>输入<code>theme</code></li></ul><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/vscode_choice_theme.png" alt="img"></p><ul><li>进入首选项-&gt;颜色主题,然后直接就选择<code>monokai</code>主题</li></ul><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/vscode_choice_theme2.png" alt="img"></p><ul><li><p>现在你会神奇的发现,当前主题和sublime一样一样的了呢!</p></li><li><p><code>sublime</code>的主题<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/sublime_theme.png" alt="img"></p></li><li><p><code>vscode</code>的主题<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/vscode_theme.png" alt="img"></p></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Visual Studio Code引入jetbrains快捷键</title>
      <link href="ide/vscode-idea-key-bindings/"/>
      <url>ide/vscode-idea-key-bindings/</url>
      
        <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言:"></a>前言:</h3><p>相信很多学习编程的小伙伴都用过jetbrains系列的ide吧,毕竟它们很专业<br>但是有时候我们可能需要一个更轻量级的ide,比如vscode,刚开始使用,可能你很不适应它的一些快捷键习惯<br>今天小编就教大家将Visual Studio Code打造成轻量级的jetbrains  </p><h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>快捷键对于编辑器就相当于八倍镜对于98K  </p><ul><li>别管别的,在vscode任意界面,直接就按<code>ctrl+shift+k</code>和<code>ctrl+shift+m</code></li></ul><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/vscode_keymap.png" alt="img"></p><ul><li>在搜索栏中输入<code>intelliJ idea keybindings</code>,并选择第一个</li></ul><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/vscode_keymap2.png" alt="img"></p><ul><li>在右边的详情页面,直接点击安装后,重启编辑器即可使用</li></ul><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/vscode_keymap3.png" alt="img"></p><p>后续内容更加精彩,请持续关注</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>如何在自己博文中自动跳转到其他链接位置</title>
      <link href="front/js/blog-href/"/>
      <url>front/js/blog-href/</url>
      
        <content type="html"><![CDATA[<p>有些小伙伴看我的博客中有自动跳转到其他博文的内容,感觉很厉害</p><p>甚至有<a href="https://caoyang7.github.io/">同学</a>感叹到:这也太好了吧!</p><h3 id="不多BB-直接上代码"><a href="#不多BB-直接上代码" class="headerlink" title="不多BB,直接上代码"></a>不多BB,直接上代码</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">window.location.href&#x3D;&#39;https:&#x2F;&#x2F;victorfengming.gitee.io&#x2F;2019&#x2F;09&#x2F;blog-href&#x2F;&#39;;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure><h3 id="简单解释-不用仔细看"><a href="#简单解释-不用仔细看" class="headerlink" title="简单解释(不用仔细看)"></a>简单解释(不用仔细看)</h3><p>其实原理很简单,说破了就感觉很low了</p><p>首先,在jekyll的模板中,markdown文件中可以嵌入html标签,在最终的页面上会被渲染成为页面中的元素内容</p><p>所以,script标签他也不例外,这样我们只需要在文档加载时,直接进行js的跳转动作就行了</p><p>这样你直接将我上面的代码粘贴到你的博客的模板中的md文件中,就直接就成了(其中href后面的地址可以根据你自己的地址来进行更改)</p><p>这个小功能看似没什么用,但是对于一些喜欢fock其他人博客的同学,这简直就是神奇的工具啊!!!</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>sublime一键格式化</title>
      <link href="ide/sublime/sublime-format-htmlcssjs/"/>
      <url>ide/sublime/sublime-format-htmlcssjs/</url>
      
        <content type="html"><![CDATA[<div class="htmledit_views" id="content_views">    <p>1.使用快捷键ctrl+shift+p调出控制台，输入install package，然后输入<span>html-css-js prettify</span>，进行下载</p><p>2.下载完成后，在preference打开package settings，会出现如下内容：</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180427160941871?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNjg5MjEwNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt=""></p><p><span>html-css-js prettify</span>安装成功。</p><p>3.具体的快捷键在preference &gt; package setting &gt; html/css/js prettify &gt; keyboard-shortcuts-default中</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180427161403345?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNjg5MjEwNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt=""><br></p><p><br></p><p><strong><span style="color:#000000;">注意：容易出现的错误！</span></strong></p><p>博主第一次使用时，按下ctrl + shift +h并没有奏效，发现这插件依赖node.js，所以要下载node.js（下载node.js不要等级太低）</p><p>node.js下载地址：http://nodejs.cn/download/</p><p>下载后使用cmd，进入下载的目录，使用node.exe --version</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180427161958508?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNjg5MjEwNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt=""></p><p>这样node.js就安装成功了！</p><p>然后在sublime中的preference &gt; package setting &gt; html/css/js prettify &gt; plugin-options-default中修改</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180427162321946?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNjg5MjEwNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt=""></p><p>红标处改为node的安装地址</p><p>再次使用ctrl + shift + h就可以格式化html/css/js了</p><p>ps:</p><p>&nbsp;&nbsp;&nbsp; 可能会有热键冲突，本人使用搜狗输入法，使用ctrl + shift + h就是换搜狗输入法的皮肤，要切换在电脑自带的输入法下的英文才可以使用！<br></p>                                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> sublime </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>sublime快捷键和设置配置</title>
      <link href="ide/sublime/sublime-keybings-settings/"/>
      <url>ide/sublime/sublime-keybings-settings/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>很多小伙伴使用jetbrains系列的编辑器后,在使用轻量级的sublime,可能会有一些设置和快捷键习惯不适应<br>小编今天就给大家一些常用的sublime设置和快捷键的配置</p><h3 id="设置"><a href="#设置" class="headerlink" title="设置"></a>设置</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    &#x2F;&#x2F; 颜色主题</span><br><span class="line">    &quot;color_scheme&quot;: &quot;Packages&#x2F;Color Scheme - Default&#x2F;Monokai.sublime-color-scheme&quot;,</span><br><span class="line">    &#x2F;&#x2F; 自动保存</span><br><span class="line">    &quot;expand_tabs_on_save&quot;: true,</span><br><span class="line">    &#x2F;&#x2F; 字体大小</span><br><span class="line">    &quot;font_size&quot;: 18,</span><br><span class="line">    </span><br><span class="line">    &quot;ignored_packages&quot;:</span><br><span class="line">    [</span><br><span class="line">        &quot;Vintage&quot;</span><br><span class="line">    ],</span><br><span class="line">    &quot;save_on_focus_lost&quot;: true,</span><br><span class="line">    &#x2F;&#x2F; 制表符宽度</span><br><span class="line">    &quot;tab_size&quot;: 4,</span><br><span class="line">    &#x2F;&#x2F; 主题</span><br><span class="line">    &quot;theme&quot;: &quot;Default.sublime-theme&quot;,</span><br><span class="line">    &#x2F;&#x2F; 自动转换为空格</span><br><span class="line">    &quot;translate_tabs_to_spaces&quot;: true,</span><br><span class="line">    &#x2F;&#x2F; 自动换行</span><br><span class="line">    &quot;word_wrap&quot;:true,</span><br><span class="line">    &#x2F;&#x2F; 设置不检查更新</span><br><span class="line">    &quot;update_check&quot;:false,</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="快捷键"><a href="#快捷键" class="headerlink" title="快捷键"></a>快捷键</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">[</span><br><span class="line">    &#x2F;&#x2F; 选取相同的单词</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+shift+d&quot;], &quot;command&quot;: &quot;find_under_expand&quot; &#125;,</span><br><span class="line">    &#x2F;&#x2F; 快速复制一行</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+d&quot;], &quot;command&quot;: &quot;duplicate_line&quot; &#125;,</span><br><span class="line">    &#x2F;&#x2F; 运行</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+shift+f10&quot;], &quot;command&quot;: &quot;build&quot; &#125;,</span><br><span class="line">    &#x2F;&#x2F; 小换行</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;shift+enter&quot;], &quot;command&quot;: &quot;run_macro_file&quot;, &quot;args&quot;: &#123;&quot;file&quot;: &quot;res:&#x2F;&#x2F;Packages&#x2F;Default&#x2F;Add Line.sublime-macro&quot;&#125; &#125;,</span><br><span class="line">    &#x2F;&#x2F; 重复上一个动作</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+shift+k&quot;], &quot;command&quot;: &quot;redo_or_repeat&quot; &#125;,</span><br><span class="line">    &#x2F;&#x2F; 删除当前行</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+y&quot;], &quot;command&quot;: &quot;run_macro_file&quot;, &quot;args&quot;: &#123;&quot;file&quot;: &quot;res:&#x2F;&#x2F;Packages&#x2F;Default&#x2F;Delete Line.sublime-macro&quot;&#125; &#125;,</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F; 带输入栏 运行python 程序</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+f10&quot;], &quot;caption&quot;: &quot;SublimeREPL:Python&quot;, </span><br><span class="line">                      &quot;command&quot;: &quot;run_existing_window_command&quot;, &quot;args&quot;:</span><br><span class="line">                      &#123;</span><br><span class="line">                           &quot;id&quot;: &quot;repl_python_run&quot;,</span><br><span class="line">                           &quot;file&quot;: &quot;config&#x2F;Python&#x2F;Main.sublime-menu&quot;</span><br><span class="line">                      &#125; </span><br><span class="line">    &#125;,</span><br><span class="line">    &#x2F;&#x2F; 查找替换</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+r&quot;], &quot;command&quot;: &quot;show_panel&quot;, &quot;args&quot;: &#123;&quot;panel&quot;: &quot;replace&quot;, &quot;reverse&quot;: false&#125; &#125;,</span><br><span class="line">    &#x2F;&#x2F; 交换快捷键</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+h&quot;], &quot;command&quot;: &quot;show_overlay&quot;, &quot;args&quot;: &#123;&quot;overlay&quot;: &quot;goto&quot;, &quot;text&quot;: &quot;@&quot;&#125; &#125;,</span><br><span class="line">    &#x2F;&#x2F; prettify中的代码格式化</span><br><span class="line">    &#x2F;&#x2F; &#123; &quot;keys&quot;: [&quot;ctrl+shift+h&quot;], &quot;command&quot;: &quot;replace_next&quot; &#125;,</span><br><span class="line">    &#x2F;&#x2F; prettify 修改</span><br><span class="line">    &#123; &quot;keys&quot;: [&quot;ctrl+alt+l&quot;], &quot;command&quot;: &quot;htmlprettify&quot; &#125;,</span><br><span class="line">    </span><br><span class="line">]</span><br></pre></td></tr></table></figure><h3 id="找不到设置的同学看这里"><a href="#找不到设置的同学看这里" class="headerlink" title="找不到设置的同学看这里"></a>找不到设置的<a href="https://caoyang7.github.io/">同学</a>看这里</h3><p>在sublime菜单栏中点击Preferences(首选项)-&gt;settings(设置)<br>在sublime菜单栏中点击Preferences(首选项)-&gt;key bindings(快捷键)</p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/sublime_settings.png" alt="sublime_setting"></p><p>如图,左边的是默认设置,在右边粘贴你的设置配置代码即可</p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/sublime_settings2.png" alt="sublime_setting"></p><p>如图,左边的是默认快捷键,在右边粘贴你的自定义快捷键即可</p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/ide/sublime_settings3.png" alt="sublime_setting"></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> sublime </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue CLI的安装</title>
      <link href="front/vue/old/vue-cli-install/"/>
      <url>front/vue/old/vue-cli-install/</url>
      
        <content type="html"><![CDATA[<div class="warning custom-block"><p class="custom-block-title">关于旧版本</p> <p>Vue CLI 的包名称由 <code>vue-cli</code> 改成了 <code>@vue/cli</code>。如果你已经全局安装了旧版本的 <code>vue-cli</code> (1.x 或 2.x)，你需要先通过 <code>npm uninstall vue-cli -g</code> 或 <code>yarn global remove vue-cli</code> 卸载它。</p></div><div class="tip custom-block"><p class="custom-block-title">Node 版本要求</p> <p>Vue CLI 需要 <a href="https://nodejs.org/" target="_blank" rel="noopener noreferrer">Node.js<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 8.9 或更高版本 (推荐 8.11.0+)。你可以使用 <a href="https://github.com/creationix/nvm" target="_blank" rel="noopener noreferrer">nvm<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 或 <a href="https://github.com/coreybutler/nvm-windows" target="_blank" rel="noopener noreferrer">nvm-windows<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 在同一台电脑中管理多个 Node 版本。</p></div><p>可以使用下列任一命令安装这个新的包：</p><div class="language-bash extra-class"><pre class="language-bash"><code><span class="token function">npm</span> <span class="token function">install</span> -g @vue/cli<span class="token comment"># OR</span><span class="token function">yarn</span> global <span class="token function">add</span> @vue/cli</code></pre></div><p>安装之后，你就可以在命令行中访问 <code>vue</code> 命令。你可以通过简单运行 <code>vue</code>，看看是否展示出了一份所有可用命令的帮助信息，来验证它是否安装成功。</p><p>你还可以用这个命令来检查其版本是否正确 (3.x)：</p><div class="language-bash extra-class"><pre class="language-bash"><code>vue --version</code></pre></div><p>如果显示出了版本号的信息,即表示vue安装成功</p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/vue/vuejs3.png" alt="vue-v"></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>初始化vue项目并启动</title>
      <link href="front/vue/old/vue-init-run/"/>
      <url>front/vue/old/vue-init-run/</url>
      
        <content type="html"><![CDATA[<h3 id="初始化vue项目"><a href="#初始化vue项目" class="headerlink" title="初始化vue项目"></a>初始化vue项目</h3><p>项目起名为<code>vue-playlist</code></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">victor@asus:~<span class="regexp">/WebstormProjects/</span>vuejs/vue_demo2$ vue init webpack vue-playlist</span><br></pre></td></tr></table></figure><p>确认项目名字,这里我们直接就一个回车,默认的名字不用改</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">? Project name vue-playlist</span><br></pre></td></tr></table></figure><p>下面是添加对于项目的描述</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">? Project description Vue基础知识</span><br></pre></td></tr></table></figure><p>作者的信息,默认就行了,直接就一个回车</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">? Author fengming &lt;victorfm@163.com&gt;</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">? Vue build standalone</span><br></pre></td></tr></table></figure><p>下面的对于我们新手来说暂时不需要,直接就一个no就行了哦 </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">? Install vue-router? No</span><br><span class="line">? Use ESLint to lint your code? No</span><br><span class="line">? Set up unit tests No</span><br><span class="line">? Setup e2e tests with Nightwatch? No</span><br></pre></td></tr></table></figure><p>这里问我们是否运行npm来创建项目</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">? Should we run &#96;npm install&#96; for you after the project has been created? (recommended) np</span><br><span class="line">m</span><br><span class="line"></span><br><span class="line">   vue-cli · Generated &quot;vue-playlist&quot;.</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>下面在安装项目所需要的依赖</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"># Installing project dependencies ...</span><br><span class="line"># &#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;</span><br><span class="line"></span><br><span class="line">npm WARN deprecated extract-text-webpack-plugin@3.0.2: Deprecated. Please use https:&#x2F;&#x2F;github.com&#x2F;webpack-contrib&#x2F;mini-css-extract-plugin</span><br><span class="line">npm WARN deprecated browserslist@2.11.3: Browserslist 2 could fail on reading Browserslist &gt;3.0 config used in other tools.</span><br><span class="line">npm WARN deprecated bfj-node4@5.3.1: Switch to the &#96;bfj&#96; package for fixes and new features!</span><br><span class="line">npm WARN deprecated flatten@1.0.2: I wrote this module a very long time ago; you should use something else.</span><br><span class="line">npm WARN deprecated browserslist@1.7.7: Browserslist 2 could fail on reading Browserslist &gt;3.0 config used in other tools.</span><br><span class="line"></span><br><span class="line">&gt; core-js@2.6.9 postinstall &#x2F;home&#x2F;victor&#x2F;WebstormProjects&#x2F;vuejs&#x2F;vue_demo2&#x2F;vue-playlist&#x2F;node_modules&#x2F;core-js</span><br><span class="line">&gt; node scripts&#x2F;postinstall || echo &quot;ignore&quot;</span><br><span class="line"></span><br><span class="line">Thank you for using core-js ( https:&#x2F;&#x2F;github.com&#x2F;zloirock&#x2F;core-js ) for polyfilling JavaScript standard library!</span><br><span class="line"></span><br><span class="line">The project needs your help! Please consider supporting of core-js on Open Collective or Patreon: </span><br><span class="line">&gt; https:&#x2F;&#x2F;opencollective.com&#x2F;core-js </span><br><span class="line">&gt; https:&#x2F;&#x2F;www.patreon.com&#x2F;zloirock </span><br><span class="line"></span><br><span class="line">Also, the author of core-js ( https:&#x2F;&#x2F;github.com&#x2F;zloirock ) is looking for a good job -)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&gt; uglifyjs-webpack-plugin@0.4.6 postinstall &#x2F;home&#x2F;victor&#x2F;WebstormProjects&#x2F;vuejs&#x2F;vue_demo2&#x2F;vue-playlist&#x2F;node_modules&#x2F;webpack&#x2F;node_modules&#x2F;uglifyjs-webpack-plugin</span><br><span class="line">&gt; node lib&#x2F;post_install.js</span><br><span class="line"></span><br><span class="line">npm notice created a lockfile as package-lock.json. You should commit this file.</span><br><span class="line">npm WARN ajv-keywords@3.4.1 requires a peer of ajv@^6.9.1 but none is installed. You must install peer dependencies yourself.</span><br><span class="line">npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules&#x2F;fsevents):</span><br><span class="line">npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted &#123;&quot;os&quot;:&quot;darwin&quot;,&quot;arch&quot;:&quot;any&quot;&#125; (current: &#123;&quot;os&quot;:&quot;linux&quot;,&quot;arch&quot;:&quot;x64&quot;&#125;)</span><br><span class="line"></span><br><span class="line">added 1215 packages from 670 contributors and audited 11812 packages in 156.77s</span><br><span class="line">found 10 vulnerabilities (6 moderate, 4 high)</span><br><span class="line">  run &#96;npm audit fix&#96; to fix them, or &#96;npm audit&#96; for details</span><br></pre></td></tr></table></figure><p>到这里项目初始化成功</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># Project initialization finished!</span><br><span class="line"># &#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;</span><br></pre></td></tr></table></figure><p>需要我们进入项目目录,使用npm来启动项目</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">To get started:</span><br><span class="line"></span><br><span class="line">  cd vue-playlist</span><br><span class="line">  npm run dev</span><br><span class="line">  </span><br><span class="line">Documentation can be found at https:&#x2F;&#x2F;vuejs-templates.github.io&#x2F;webpack</span><br></pre></td></tr></table></figure><p>进入项目文件夹中后,执行启动命令<code>npm run dev</code></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">victor@asus:~<span class="regexp">/WebstormProjects/</span>vuejs/vue_demo2/vue-playlist$ npm run dev</span><br><span class="line"></span><br><span class="line">&gt; vue-playlist@<span class="number">1.0</span><span class="number">.0</span> dev /home/victor/WebstormProjects/vuejs/vue_demo2/vue-playlist</span><br><span class="line">&gt; webpack-dev-server --inline --progress --config build/webpack.dev.conf.js</span><br><span class="line"></span><br><span class="line"> <span class="number">12</span>% building modules <span class="number">20</span>/<span class="number">29</span> modules <span class="number">9</span> active ...js/vue_demo2/vue-playlist/src/App.vue&#123; <span class="attr">parser</span>: <span class="string">&quot;babylon&quot;</span> &#125; is deprecated; we now treat it <span class="keyword">as</span> &#123; <span class="attr">parser</span>: <span class="string">&quot;babel&quot;</span> &#125;.</span><br><span class="line"> <span class="number">95</span>% emitting                                                                        </span><br><span class="line"></span><br><span class="line"> DONE  Compiled successfully <span class="keyword">in</span> 8720ms                                            <span class="number">16</span>:<span class="number">34</span>:<span class="number">56</span></span><br><span class="line"></span><br><span class="line"> I  Your application is running here: http:<span class="comment">//localhost:8080</span></span><br><span class="line"> </span><br></pre></td></tr></table></figure><p>到这里即可在本地服务器访问你的项目了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">地址为:http:&#x2F;&#x2F;localhost:8080</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/vue/vuejs4.png" alt="vuehelloworld"></p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue的项目目录解析</title>
      <link href="front/vue/old/vue-pro-dir-analysis/"/>
      <url>front/vue/old/vue-pro-dir-analysis/</url>
      
        <content type="html"><![CDATA[<h3 id="废话不多讲-直接就一个表格"><a href="#废话不多讲-直接就一个表格" class="headerlink" title="废话不多讲,直接就一个表格"></a>废话不多讲,直接就一个表格</h3><table class="reference"><thead><tr>  <th>目录/文件</th>  <th>说明</th></tr></thead><tbody><tr>  <td>build</td>  <td>项目构建(webpack)相关代码</td></tr><tr>  <td>config</td>  <td>配置目录，包括端口号等。我们初学可以使用默认的。</td></tr><tr>  <td>node_modules</td>  <td>npm 加载的项目依赖模块</td></tr><tr>  <td>src</td>  <td><p>这里是我们要开发的目录，基本上要做的事情都在这个目录里。里面包含了几个目录及文件：</p>  <ul>  <li>assets: 放置一些图片，如logo等。</li>  <li>components: 目录里面放了一个组件文件，可以不用。</li>  <li>App.vue: 项目入口文件，我们也可以直接将组件写这里，而不使用 components 目录。</li>  <li>main.js: 项目的核心文件。</li>  </ul>  </td></tr><tr>  <td>static</td>  <td>静态资源目录，如图片、字体等。</td></tr><tr>  <td>test</td>  <td>初始测试目录，可删除</td></tr><tr>  <td>.xxxx文件</td>  <td>这些是一些配置文件，包括语法配置，git配置等。</td></tr><tr>  <td>index.html</td>  <td>首页入口文件，你可以添加一些 meta 信息或统计代码啥的。</td></tr><tr>  <td>package.json</td>  <td>项目配置文件。</td></tr><tr>  <td>README.md</td>  <td>项目的说明文档，markdown 格式</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>ES6中的const命令</title>
      <link href="front/es6/es6-const-detial/"/>
      <url>front/es6/es6-const-detial/</url>
      
        <content type="html"><![CDATA[<p><code>const</code>声明一个只读的常量。一旦声明，常量的值就不能改变。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const PI &#x3D; 3.1415;</span><br><span class="line">PI &#x2F;&#x2F; 3.1415</span><br><span class="line"></span><br><span class="line">PI &#x3D; 3;</span><br><span class="line">&#x2F;&#x2F; TypeError: Assignment to constant variable.</span><br></pre></td></tr></table></figure><p>上面代码表明改变常量的值会报错。</p><p><code>const</code>声明的变量不得改变值，这意味着，const一旦声明变量，就必须立即初始化，不能留到以后赋值。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">const foo;</span><br><span class="line">&#x2F;&#x2F; SyntaxError: Missing initializer in const declaration</span><br></pre></td></tr></table></figure><p>上面代码表示，对于const来说，只声明不赋值，就会报错。</p><p><code>const</code>的作用域与let命令相同：只在声明所在的块级作用域内有效。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">if (true) &#123;</span><br><span class="line">  const MAX &#x3D; 5;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">MAX &#x2F;&#x2F; Uncaught ReferenceError: MAX is not defined</span><br></pre></td></tr></table></figure><p><code>const</code>命令声明的常量也是不提升，同样存在暂时性死区，只能在声明的位置后面使用。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">if (true) &#123;</span><br><span class="line">  console.log(MAX); &#x2F;&#x2F; ReferenceError</span><br><span class="line">  const MAX &#x3D; 5;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面代码在常量MAX声明之前就调用，结果报错。</p><p><code>const</code>声明的常量，也与let一样不可重复声明。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">var message &#x3D; &quot;Hello!&quot;;</span><br><span class="line">let age &#x3D; 25;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 以下两行都会报错</span><br><span class="line">const message &#x3D; &quot;Goodbye!&quot;;</span><br><span class="line">const age &#x3D; 30;</span><br></pre></td></tr></table></figure><p>对于复合类型的变量，变量名不指向数据，而是指向数据所在的地址。const命令只是保证变量名指向的地址不变，并不保证该地址的数据不变，所以将一个对象声明为常量必须非常小心。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">const foo &#x3D; &#123;&#125;;</span><br><span class="line">foo.prop &#x3D; 123;</span><br><span class="line"></span><br><span class="line">foo.prop</span><br><span class="line">&#x2F;&#x2F; 123</span><br><span class="line"></span><br><span class="line">foo &#x3D; &#123;&#125;; &#x2F;&#x2F; TypeError: &quot;foo&quot; is read-only</span><br></pre></td></tr></table></figure><p>上面代码中，常量foo储存的是一个地址，这个地址指向一个对象。不可变的只是这个地址，即不能把foo指向另一个地址，但对象本身是可变的，所以依然可以为其添加新属性。</p><p>下面是另一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">const a &#x3D; [];</span><br><span class="line">a.push(&#39;Hello&#39;); &#x2F;&#x2F; 可执行</span><br><span class="line">a.length &#x3D; 0;    &#x2F;&#x2F; 可执行</span><br><span class="line">a &#x3D; [&#39;Dave&#39;];    &#x2F;&#x2F; 报错</span><br></pre></td></tr></table></figure><p>上面代码中，常量a是一个数组，这个数组本身是可写的，但是如果将另一个数组赋值给a，就会报错。</p><p>如果真的想将对象冻结，应该使用Object.freeze方法。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const foo &#x3D; Object.freeze(&#123;&#125;);</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 常规模式时，下面一行不起作用；</span><br><span class="line">&#x2F;&#x2F; 严格模式时，该行会报错</span><br><span class="line">foo.prop &#x3D; 123;</span><br></pre></td></tr></table></figure><p>上面代码中，常量foo指向一个冻结的对象，所以添加新属性不起作用，严格模式时还会报错。</p><p>除了将对象本身冻结，对象的属性也应该冻结。下面是一个将对象彻底冻结的函数。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">var constantize &#x3D; (obj) &#x3D;&gt; &#123;</span><br><span class="line">  Object.freeze(obj);</span><br><span class="line">  Object.keys(obj).forEach( (key, value) &#x3D;&gt; &#123;</span><br><span class="line">    if ( typeof obj[key] &#x3D;&#x3D;&#x3D; &#39;object&#39; ) &#123;</span><br><span class="line">      constantize( obj[key] );</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>ES5只有两种声明变量的方法：var命令和function命令。ES6除了添加let和const命令，后面章节还会提到，另外两种声明变量的方法：import命令和class命令。所以，ES6一共有6种声明变量的方法。</p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>ES6中的let命令</title>
      <link href="front/es6/es6-let-detial/"/>
      <url>front/es6/es6-let-detial/</url>
      
        <content type="html"><![CDATA[<h3 id="基本用法"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法</h3><p>ES6新增了let命令，用来声明变量。它的用法类似于var，但是所声明的变量，只在let命令所在的代码块内有效。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  let a &#x3D; 10;</span><br><span class="line">  var b &#x3D; 1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">a &#x2F;&#x2F; ReferenceError: a is not defined.</span><br><span class="line">b &#x2F;&#x2F; 1</span><br></pre></td></tr></table></figure><p>上面代码在代码块之中，分别用let和var声明了两个变量。然后在代码块之外调用这两个变量，结果let声明的变量报错，var声明的变量返回了正确的值。这表明，let声明的变量只在它所在的代码块有效。</p><p>for循环的计数器，就很合适使用let命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for (let i &#x3D; 0; i &lt; 10; i++) &#123;&#125;</span><br><span class="line"></span><br><span class="line">console.log(i);</span><br><span class="line">&#x2F;&#x2F;ReferenceError: i is not defined</span><br></pre></td></tr></table></figure><p>上面代码中，计数器i只在for循环体内有效，在循环体外引用就会报错。</p><p>下面的代码如果使用var，最后输出的是10。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">var a &#x3D; [];</span><br><span class="line">for (var i &#x3D; 0; i &lt; 10; i++) &#123;</span><br><span class="line">  a[i] &#x3D; function () &#123;</span><br><span class="line">    console.log(i);</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br><span class="line">a[6](); &#x2F;&#x2F; 10</span><br></pre></td></tr></table></figure><p>上面代码中，变量i是var声明的，在全局范围内都有效。所以每一次循环，新的i值都会覆盖旧值，导致最后输出的是最后一轮的i的值。</p><p>如果使用let，声明的变量仅在块级作用域内有效，最后输出的是6。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">var a &#x3D; [];</span><br><span class="line">for (let i &#x3D; 0; i &lt; 10; i++) &#123;</span><br><span class="line">  a[i] &#x3D; function () &#123;</span><br><span class="line">    console.log(i);</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br><span class="line">a[6](); &#x2F;&#x2F; 6</span><br></pre></td></tr></table></figure><p>上面代码中，变量i是let声明的，当前的i只在本轮循环有效，所以每一次循环的i其实都是一个新的变量，所以最后输出的是6。</p><h3 id="不存在变量提升"><a href="#不存在变量提升" class="headerlink" title="不存在变量提升"></a>不存在变量提升</h3><p>let不像var那样会发生“变量提升”现象。所以，变量一定要在声明后使用，否则报错。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">console.log(foo); &#x2F;&#x2F; 输出undefined</span><br><span class="line">console.log(bar); &#x2F;&#x2F; 报错ReferenceError</span><br><span class="line"></span><br><span class="line">var foo &#x3D; 2;</span><br><span class="line">let bar &#x3D; 2;</span><br></pre></td></tr></table></figure><p>上面代码中，变量foo用var命令声明，会发生变量提升，即脚本开始运行时，变量foo已经存在了，但是没有值，所以会输出undefined。变量bar用let命令声明，不会发生变量提升。这表示在声明它之前，变量bar是不存在的，这时如果用到它，就会抛出一个错误。</p><h3 id="暂时性死区"><a href="#暂时性死区" class="headerlink" title="暂时性死区"></a>暂时性死区</h3><p>只要块级作用域内存在let命令，它所声明的变量就“绑定”（binding）这个区域，不再受外部的影响。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">var tmp &#x3D; 123;</span><br><span class="line"></span><br><span class="line">if (true) &#123;</span><br><span class="line">  tmp &#x3D; &#39;abc&#39;; &#x2F;&#x2F; ReferenceError</span><br><span class="line">  let tmp;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面代码中，存在全局变量tmp，但是块级作用域内let又声明了一个局部变量tmp，导致后者绑定这个块级作用域，所以在let声明变量前，对tmp赋值会报错。</p><p>ES6明确规定，如果区块中存在let和const命令，这个区块对这些命令声明的变量，从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量，就会报错。</p><p>总之，在代码块内，使用let命令声明变量之前，该变量都是不可用的。这在语法上，称为“暂时性死区”（temporal dead zone，简称TDZ）。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">if (true) &#123;</span><br><span class="line">  &#x2F;&#x2F; TDZ开始</span><br><span class="line">  tmp &#x3D; &#39;abc&#39;; &#x2F;&#x2F; ReferenceError</span><br><span class="line">  console.log(tmp); &#x2F;&#x2F; ReferenceError</span><br><span class="line"></span><br><span class="line">  let tmp; &#x2F;&#x2F; TDZ结束</span><br><span class="line">  console.log(tmp); &#x2F;&#x2F; undefined</span><br><span class="line"></span><br><span class="line">  tmp &#x3D; 123;</span><br><span class="line">  console.log(tmp); &#x2F;&#x2F; 123</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面代码中，在let命令声明变量tmp之前，都属于变量tmp的“死区”。</p><p>“暂时性死区”也意味着typeof不再是一个百分之百安全的操作。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">typeof x; &#x2F;&#x2F; ReferenceError</span><br><span class="line">let x;</span><br></pre></td></tr></table></figure><p>上面代码中，变量x使用let命令声明，所以在声明之前，都属于x的“死区”，只要用到该变量就会报错。因此，typeof运行时就会抛出一个ReferenceError。</p><p>作为比较，如果一个变量根本没有被声明，使用typeof反而不会报错。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">typeof undeclared_variable &#x2F;&#x2F; &quot;undefined&quot;</span><br></pre></td></tr></table></figure><p>上面代码中，undeclared_variable是一个不存在的变量名，结果返回“undefined”。所以，在没有let之前，typeof运算符是百分之百安全的，永远不会报错。现在这一点不成立了。这样的设计是为了让大家养成良好的编程习惯，变量一定要在声明之后使用，否则就报错。</p><p>有些“死区”比较隐蔽，不太容易发现。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function bar(x &#x3D; y, y &#x3D; 2) &#123;</span><br><span class="line">  return [x, y];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">bar(); &#x2F;&#x2F; 报错</span><br></pre></td></tr></table></figure><p>上面代码中，调用bar函数之所以报错（某些实现可能不报错），是因为参数x默认值等于另一个参数y，而此时y还没有声明，属于”死区“。如果y的默认值是x，就不会报错，因为此时x已经声明了。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function bar(x &#x3D; 2, y &#x3D; x) &#123;</span><br><span class="line">  return [x, y];</span><br><span class="line">&#125;</span><br><span class="line">bar(); &#x2F;&#x2F; [2, 2]</span><br></pre></td></tr></table></figure><p>ES6规定暂时性死区和let、const语句不出现变量提升，主要是为了减少运行时错误，防止在变量声明前就使用这个变量，从而导致意料之外的行为。这样的错误在ES5是很常见的，现在有了这种规定，避免此类错误就很容易了。</p><p>总之，暂时性死区的本质就是，只要一进入当前作用域，所要使用的变量就已经存在了，但是不可获取，只有等到声明变量的那一行代码出现，才可以获取和使用该变量。</p><h3 id="不允许重复声明"><a href="#不允许重复声明" class="headerlink" title="不允许重复声明"></a>不允许重复声明</h3><p>let不允许在相同作用域内，重复声明同一个变量。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 报错</span><br><span class="line">function () &#123;</span><br><span class="line">  let a &#x3D; 10;</span><br><span class="line">  var a &#x3D; 1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 报错</span><br><span class="line">function () &#123;</span><br><span class="line">  let a &#x3D; 10;</span><br><span class="line">  let a &#x3D; 1;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>因此，不能在函数内部重新声明参数。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">function func(arg) &#123;</span><br><span class="line">  let arg; &#x2F;&#x2F; 报错</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function func(arg) &#123;</span><br><span class="line">  &#123;</span><br><span class="line">    let arg; &#x2F;&#x2F; 不报错</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>ES6中let和var的区别</title>
      <link href="front/es6/es6-let-var-diff/"/>
      <url>front/es6/es6-let-var-diff/</url>
      
        <content type="html"><![CDATA[<p><a href="https://www.jianshu.com/p/759f120910e8">原文链接</a></p><section class="ouvJEz">    <article class="_2rhmJa"><p>let是在ES6中新引入的关键字，用来改进var带来的各种问题。<br>let和var相比，大致有下面几个方面的不同：</p><ul><li>作用域<br>通过let定义的变量，作用域是在定义它的块级代码以及其中包括的子块中，并且无法在全局作用域添加变量。<br>通过var定义的变量，作用域为包括它的函数作用域或者全局作用域。</li></ul><pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token keyword">function</span> <span class="token function">varTest</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>  <span class="token keyword">var</span> x <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token keyword">var</span> x <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>  <span class="token comment">// same variable!</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// 2</span>  <span class="token punctuation">&#125;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// 2</span><span class="token punctuation">&#125;</span><p><span class="token keyword">function</span> <span class="token function">letTest</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><br>  <span class="token keyword">let</span> x <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span><br>  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><br>    <span class="token keyword">let</span> x <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>  <span class="token comment">// different variable</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// 2</span><br>  <span class="token punctuation">&#125;</span><br>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// 1</span><br><span class="token punctuation">&#125;</span><br><span class="token comment">// let 无法在全局作用域中定义变量</span><br><span class="token keyword">var</span> x <span class="token operator">=</span> <span class="token string">‘global’</span><span class="token punctuation">;</span><br><span class="token keyword">let</span> y <span class="token operator">=</span> <span class="token string">‘global’</span><span class="token punctuation">;</span><br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// “global”</span><br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>y<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// undefined</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><p>let的block scope的特性，可以用来实现class的私有成员。在let之前，一般是通过闭包的特性实现的。代码如下：</p><pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token keyword">var</span> Thing <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token comment">// block scope</span><span class="token punctuation">&#123;</span>  <span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token number">1</span>  <span class="token function-variable function">Thing</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">'something'</span>  <span class="token comment">// 创建公共成员</span>  <span class="token punctuation">&#125;</span>  <span class="token class-name">Thing</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">showPublic</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name  <span class="token punctuation">&#125;</span>  <span class="token class-name">Thing</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">showPrivate</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>  <span class="token comment">// counter变为了私有成员，只能通过showPrivate进行访问</span>    counter <span class="token operator">++</span>    <span class="token keyword">return</span> counter  <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token keyword">var</span> thing <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Thing</span><span class="token punctuation">(</span><span class="token punctuation">)</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">.</span>name<span class="token punctuation">)</span>  <span class="token comment">// something</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">.</span><span class="token function">showPublic</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment">// something</span>thing<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">'otherthing'</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">.</span><span class="token function">showPublic</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment">// otherthing</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">.</span><span class="token function">showPrivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 2</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">)</span>  <span class="token comment">// Thing &#123;name: "otherthing"&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>我们可以和之前使用闭包的方法进行比较下：</p><pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token keyword">var</span> Thing <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>  <span class="token keyword">var</span> counter <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>  <span class="token keyword">return</span> <span class="token punctuation">&#123;</span>    name<span class="token punctuation">:</span> <span class="token string">'something'</span><span class="token punctuation">,</span>    <span class="token function-variable function">showPublic</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>    <span class="token function-variable function">showPrivate</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>      counter<span class="token operator">++</span>      <span class="token keyword">return</span> counter    <span class="token punctuation">&#125;</span>  <span class="token punctuation">&#125;</span>   <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><p><span class="token keyword">var</span> thing <span class="token operator">=</span> Thing<br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">.</span>name<span class="token punctuation">)</span>  <span class="token comment">// something</span><br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">.</span><span class="token function">showPublic</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment">// something</span><br>thing<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">‘otherthing’</span><br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">.</span><span class="token function">showPublic</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment">// otherthing</span><br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">.</span><span class="token function">showPrivate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 2</span><br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>thing<span class="token punctuation">)</span>  <span class="token comment">// Thing &#123;name: “otherthing”&#125;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><p>两个的差异，在于一个使用了property，通过new创建新对象。一个是直接返回一个对象。后面要重新看下原型链的问题，再对其总结下。</p><ul><li>重复声明<br>通过let定义的变量，在同一个作用域内，不可以重复声明。<br>通过var定义的变量，在同一个作用域内，重复声明，在生成执行上下文的时候，会无视后面的声明。</li></ul><pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token comment">// 报错</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>  <span class="token keyword">let</span> a <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>  <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token comment">// 报错</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>  <span class="token keyword">let</span> a <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>  <span class="token keyword">let</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token comment">// 报错</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>  <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>  <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token comment">// 1</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>需要注意，当在switch-case语句中，如果case语句没有使用{}包括，则视为同一个作用域。</p><ul><li>临时死区引起的提升等问题<br>我们知道在代码执行之前，会先扫描所有域内的var声明的变量，将其先进行初始化为undefined，然后再执行代码，也就是所谓的“提升”现象。<br>但对于let声明的变量而言，则有所不同。在代码执行之前的扫描，同样也会对let变量进行“提升”，但并没有将其置为undefined。let定义的变量虽然经历了提升，但在没有执行到初始化它的代码前，该变量并没有被初始化，如果此时访问的话，会被置为<a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/ReferenceError" target="_blank" rel="nofollow">ReferenceError</a>错误。从代码块开始到执行到let变量初始化完毕这段时间，let变量已经被声明，但不可访问。这段时间被成为临时死区。下面是几个典型的展示临时死区问题的代码：</li></ul><pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token comment">// let变量的作用域为function scope</span><span class="token keyword">function</span> <span class="token function">do_something</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>bar<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// undefined</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>foo<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ReferenceError</span>  <span class="token keyword">var</span> bar <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>  <span class="token keyword">let</span> foo <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token comment">// let变量的作用域为整段代码，</span><span class="token comment">// prints out 'undefined'</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> undeclaredVariable<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// typeof对于未声明的变量返回undefined</span><span class="token comment">// results in a 'ReferenceError'</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> i<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span><span class="token comment">// let 变量为block scope，在初始化时使用，依然会视为临时死区，只有在初始化执行完后才可以使用</span><span class="token keyword">function</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>   <span class="token keyword">var</span> foo <span class="token operator">=</span> <span class="token number">33</span><span class="token punctuation">;</span>   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>      <span class="token keyword">let</span> foo <span class="token operator">=</span> <span class="token punctuation">(</span>foo <span class="token operator">+</span> <span class="token number">55</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ReferenceError</span>   <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// let 变量在for的block scope内进行了声明，n.a对应的是在本地作用域中的let变量n。在未初始化前，通过n.a进行了访问了n，因此报错</span><span class="token keyword">function</span> <span class="token function">go</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>  <span class="token comment">// n here is defined!</span>  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Object &#123;a: [1,2,3]&#125;</span><p>  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> n <span class="token keyword">of</span> n<span class="token punctuation">.</span>a<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token comment">// ReferenceError</span><br>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">;</span><br>  <span class="token punctuation">&#125;</span><br><span class="token punctuation">&#125;</span></p><p><span class="token function">go</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>a<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p><p>Tip：需要注意的是，和<code>let</code>一起引入的<code>const</code>同样拥有“临时死区”的特性，也一样无法重复声明。</p></article></section>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue指令大全</title>
      <link href="front/vue/old/vue-command/"/>
      <url>front/vue/old/vue-command/</url>
      
        <content type="html"><![CDATA[  <section class="ouvJEz">   <h1 class="_1RuRku">Vue指令大全</h1>   <div class="rEsl9f">    <div class="s-dsoj">     <span class="_3tCVn5"><i aria-label="ic-diamond" class="anticon">       <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">        <use xlink:href="#ic-diamond"></use>       </svg></i><span>2</span></span>     <time datetime="2018-06-06T04:49:13.000Z">2018.06.06 12:49:13</time>     <span>字数 1222</span>     <span>阅读 28624</span>    </div>   </div>   <article class="_2rhmJa">    <p><h3>1. v-text</h3><br /> v-text主要用来更新textContent，可以等同于JS的text属性。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">v-text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>msg<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>     <p>这两者等价：</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">&gt;</span></span>&#123;&#123;msg&#125;&#125;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>     <hr />     <p><h3>2. v-html</h3><br /> 双大括号的方式会将数据解释为纯文本，而非HTML。为了输出真正的HTML，可以用v-html指令。它等同于JS的innerHtml属性。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-html</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>rawHtml<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>     <p>这个div的内容将会替换成属性值rawHtml，直接作为HTML进行渲染。</p>     <hr />     <p><h3>3. v-pre</h3><br /> v-pre主要用来跳过这个元素和它的子元素编译过程。可以用来显示原始的Mustache标签。跳过大量没有指令的节点加快编译。</p>     <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">v-pre</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">&#123;</span><span class="token punctuation">&#123;</span>message<span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">  //这条语句不进行编译    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">&#123;</span><span class="token punctuation">&#123;</span>message<span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token plain-text"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>     <p>最终仅显示第二个span的内容</p>     <hr />     <p><h3>4. v-cloak</h3><br /> 这个指令是用来保持在元素上直到关联实例结束时进行编译。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span> <span class="token attr-name">v-cloak</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>        &#123;&#123;message&#125;&#125;    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text/javascript<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    new Vue(&#123;      el:'#app',      data:&#123;        message:'hello world'      &#125;    &#125;)<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <p>在页面加载时会闪烁，先显示:</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>    &#123;&#123;message&#125;&#125;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>     <p>然后才会编译为：</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>    hello world!<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>     <hr />     <p><h3>5. v-once</h3><br /> v-once关联的实例，只会渲染一次。之后的重新渲染，实例极其所有的子节点将被视为静态内容跳过，这可以用于优化更新性能。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">v-once</span><span class="token punctuation">&gt;</span></span>This will never change:&#123;&#123;msg&#125;&#125;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span>  //单个元素<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-once</span><span class="token punctuation">&gt;</span></span>//有子元素    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">&gt;</span></span>comment<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>&#123;&#123;msg&#125;&#125;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>my-component</span> <span class="token attr-name"><span class="token namespace">v-once:</span>comment</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>msg<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>my-component</span><span class="token punctuation">&gt;</span></span>  //组件<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>i in list<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>&#123;&#123;i&#125;&#125;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <p>上面的例子中，msg,list即使产生改变，也不会重新渲染。</p>     <hr />     <p><h3>6. v-if</h3><br /> v-if可以实现条件渲染，Vue会根据表达式的值的真假条件来渲染元素。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>ok<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>yes<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>     <p>如果属性值ok为true，则显示。否则，不会渲染这个元素。</p>     <hr />     <p><h3>7. v-else</h3><br /> v-else是搭配v-if使用的，它必须紧跟在v-if或者v-else-if后面，否则不起作用。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>ok<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>yes<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">v-else</span><span class="token punctuation">&gt;</span></span>No<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>     <hr />     <p><h3>8. v-else-if</h3><br /> v-else-if充当v-if的else-if块，可以链式的使用多次。可以更加方便的实现switch语句。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>type==='A'<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    A<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>type==='B'<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    B<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>type==='C'<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    C<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-else</span><span class="token punctuation">&gt;</span></span>    Not A,B,C<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <hr />     <p><h3>9. v-show</h3><br /></p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span> <span class="token attr-name">v-show</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>ok<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>hello world<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>     <p>也是用于根据条件展示元素。和v-if不同的是，如果v-if的值是false，则这个元素被销毁，不在dom中。但是v-show的元素会始终被渲染并保存在dom中，它只是简单的切换css的dispaly属性。</p>     <blockquote>      <p>注意：v-if有更高的切换开销<br /> v-show有更高的初始渲染开销。<br /> 因此，如果要非常频繁的切换，则使用v-show较好；如果在运行时条件不太可能改变，则v-if较好</p>     </blockquote>     <hr />     <p><h3>10. v-for</h3><br /> 用v-for指令根据遍历数组来进行渲染<br /> 有下面两种遍历形式</p>     <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>(item,index) in items<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>   <span class="token comment">//使用in，index是一个可选参数，表示当前项的索引</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>item of items<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>   <span class="token comment">//使用of</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>     <p>下面是一个例子，并且在v-for中，拥有对父作用域属性的完全访问权限。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>item in items<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>        &#123;&#123;parent&#125;&#125;-&#123;&#123;item.text&#125;&#125;    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text/javascript<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    var example = new Vue(&#123;      el:'#app',      data:&#123;        parent:'父作用域'        items:[          &#123;text:'文本1'&#125;,          &#123;text:'文本2'&#125;        ]      &#125;    &#125;)<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <p>会被渲染为：</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">&gt;</span></span>父作用域-文本1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">&gt;</span></span>父作用域-文本2<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>     <blockquote>      <p><strong>注意：当v-for和v-if同处于一个节点时，v-for的优先级比v-if更高。这意味着v-if将运行在每个v-for循环中</strong></p>     </blockquote>     <hr />     <p><h3>11. v-bind</h3><br /> v-bind用来<strong>动态的绑定一个或者多个特性</strong>。没有参数时，可以绑定到一个包含键值对的对象。常用于动态绑定class和style。以及href等。<br /> 简写为一个冒号【 <strong>：</strong>】</p>     <p><strong>&lt;1&gt;对象语法</strong>：</p>     <pre class="line-numbers  language-jsx"><code class="  language-jsx"><span class="token comment">//进行类切换的例子</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">    &lt;!--当data里面定义的isActive等于true时，is-active这个类才会被添加起作用--&gt;    &lt;!--当data里面定义的hasError等于true时，text-danger这个类才会被添加起作用--&gt;    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">:class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>&#123;'is-active':isActive, 'text-danger':hasError&#125;<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token plain-text"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">    var app = new Vue(&#123;        el: '#app',        data: &#123;            isActive: true,              hasError: false        &#125;    &#125;)</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <p>渲染结果：</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token comment">&lt;!--因为hasError: false，所以text-danger不被渲染--&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">&quot;</span>is-active<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>     <p><strong>&lt;2&gt;数组语法</strong></p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    <span class="token comment">&lt;!--数组语法：errorClass在data对应的类一定会添加--&gt;</span>    <span class="token comment">&lt;!--is-active是对象语法，根据activeClass对应的取值决定是否添加--&gt;</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">:class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>[&#123;'is-active':activeClass&#125;,errorClass]<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>12345<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span>    var app = new Vue(&#123;        el: '#app',        data: &#123;            activeClass: false,            errorClass: 'text-danger'        &#125;    &#125;)<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <p>渲染结果：</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token comment">&lt;!--因为activeClass: false，所以is-active不被渲染--&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">&quot;</span>text-danger<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>     <p><strong>&lt;3&gt;直接绑定数据对象</strong></p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    <span class="token comment">&lt;!--在vue实例的data中定义了classObject对象，这个对象里面是所有类名及其真值--&gt;</span>    <span class="token comment">&lt;!--当里面的类的值是true时会被渲染--&gt;</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">:class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>classObject<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>12345<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span>    var app = new Vue(&#123;        el: '#app',        data: &#123;            classObject:&#123;                'is-active': false,                'text-danger':true            &#125;                   &#125;    &#125;)<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <p>渲染结果：</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token comment">&lt;!--因为'is-active': false，所以is-active不被渲染--&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">&quot;</span>text-danger<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>     <hr />     <p><h3>12. v-model</h3><br /> 这个指令用于在表单上创建<strong>双向数据绑定</strong>。<br /> v-model会忽略所有表单元素的value、checked、selected特性的初始值。因为它选择Vue实例数据做为具体的值。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">v-model</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>somebody<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>hello &#123;&#123;somebody&#125;&#125;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span>    var app = new Vue(&#123;        el: '#app',        data: &#123;            somebody:'小明'        &#125;    &#125;)<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <p>这个例子中直接在浏览器input中输入别的名字，下面的p的内容会直接跟着变。这就是双向数据绑定。</p>     <p><strong>v-model修饰符</strong><br /> <strong>&lt;1&gt; .lazy</strong><br /> 默认情况下，v-model同步输入框的值和数据。可以通过这个修饰符，转变为在change事件再同步。</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">v-model.lazy</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>msg<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>     <p><strong>&lt;2&gt; .number</strong><br /> 自动将用户的输入值转化为数值类型</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">v-model.number</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>msg<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>     <p><strong>&lt;3&gt; .trim</strong><br /> 自动过滤用户输入的首尾空格</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">v-model.trim</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>msg<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>     <hr />     <p><h3>13. v-on</h3><br /> v-on主要用来监听dom事件，以便执行一些代码块。表达式可以是一个方法名。<br /> 简写为：【 <strong>@</strong> 】</p>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>consoleLog<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span>    var app = new Vue(&#123;        el: '#app',        methods:&#123;            consoleLog:function (event) &#123;                console.log(1)            &#125;        &#125;    &#125;)<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>     <p><strong>事件修饰符</strong></p>     <ul>      <li> <code>.stop</code> 阻止事件继续传播</li>      <li> <code>.prevent</code> 事件不再重载页面</li>      <li> <code>.capture</code> 使用事件捕获模式,即元素自身触发的事件先在此处处理，然后才交由内部元素进行处理</li>      <li> <code>.self</code> 只当在 event.target 是当前元素自身时触发处理函数</li>      <li> <code>.once</code> 事件将只会触发一次</li>      <li> <code>.passive</code> 告诉浏览器你不想阻止事件的默认行为</li>     </ul>     <pre class="line-numbers  language-xml"><code class="  language-xml"><span class="token comment">&lt;!-- 阻止单击事件继续传播 --&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name"><span class="token namespace">v-on:</span>click.stop</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>doThis<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">&gt;</span></span><p><span class="token comment">&lt;!– 提交事件不再重载页面 –&gt;</span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name"><span class="token namespace">v-on:</span>submit.prevent</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>onSubmit<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span></p><p><span class="token comment">&lt;!– 修饰符可以串联 –&gt;</span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name"><span class="token namespace">v-on:</span>click.stop.prevent</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>doThat<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">&gt;</span></span></p><p><span class="token comment">&lt;!– 只有修饰符 –&gt;</span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name"><span class="token namespace">v-on:</span>submit.prevent</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span></p><p><span class="token comment">&lt;!– 添加事件监听器时使用事件捕获模式 –&gt;</span><br><span class="token comment">&lt;!– 即元素自身触发的事件先在此处处理，然后才交由内部元素进行处理 –&gt;</span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name"><span class="token namespace">v-on:</span>click.capture</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>doThis<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>…<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span></p><p><span class="token comment">&lt;!– 只当在 event.target 是当前元素自身时触发处理函数 –&gt;</span><br><span class="token comment">&lt;!– 即事件不是从内部元素触发的 –&gt;</span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name"><span class="token namespace">v-on:</span>click.self</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>doThat<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>…<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span></p><p><span class="token comment">&lt;!– 点击事件将只会触发一次 –&gt;</span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name"><span class="token namespace">v-on:</span>click.once</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>doThis<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">&gt;</span></span></p><p><span class="token comment">&lt;!– 滚动事件的默认行为 (即滚动行为) 将会立即触发 –&gt;</span><br><span class="token comment">&lt;!– 而不会等待 <code>onScroll</code> 完成  –&gt;</span><br><span class="token comment">&lt;!– 这其中包含 <code>event.preventDefault()</code> 的情况 –&gt;</span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name"><span class="token namespace">v-on:</span>scroll.passive</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>onScroll<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>…<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><br><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><br>    <blockquote><br>     <p>使用修饰符时，顺序很重要；相应的代码会以同样的顺序产生。因此，用<code>v-on:click.prevent.self</code>会<strong>阻止所有的点击</strong>，而 <code>v-on:click.self.prevent</code> 只会阻止对元素自身的点击。</p><br>    </blockquote><br>   </article></p>  </section>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue2.0 中，这两个概念是什么？</title>
      <link href="front/vue/old/vue-concept/"/>
      <url>front/vue/old/vue-concept/</url>
      
        <content type="html"><![CDATA[<p>作者：徐飞<br>链接：<a href="https://www.zhihu.com/question/51907207/answer/136559185">https://www.zhihu.com/question/51907207/answer/136559185</a><br>来源：知乎<br>著作权归作者所有。<br>商业转载请联系作者获得授权，非商业转载请注明出处。  </p><p>在我看来，渐进式代表的含义是：主张最少。  </p><p>每个框架都不可避免会有自己的一些特点，从而会对使用者有一定的要求，这些要求就是主张，主张有强有弱，它的强势程度会影响在业务开发中的使用方式。  </p><p>比如说，Angular，它两个版本都是强主张的，如果你用它，必须接受以下东西：- 必须使用它的模块机制- 必须使用它的依赖注入- 必须使用它的特殊形式定义组件（这一点每个视图框架都有，难以避免）所以Angular是带有比较强的排它性的，如果你的应用不是从头开始，而是要不断考虑是否跟其他东西集成，这些主张会带来一些困扰。<br>比如React，它也有一定程度的主张，它的主张主要是函数式编程的理念，比如说，你需要知道什么是副作用，什么是纯函数，如何隔离副作用。<br>它的侵入性看似没有Angular那么强，主要因为它是软性侵入。<br>你当然可以只用React的视图层，但几乎没有人这么用，为什么呢，因为你用了它，就会觉得其他东西都很别扭，于是你要引入Flux，Redux，Mobx之中的一个，于是你除了Redux，还要看saga，于是你要纠结业务开发过程中每个东西有没有副作用，纯不纯，甚至你连这个都可能不能忍：const getData = () =&gt; {  // 如果不存在，就在缓存中创建一个并返回  // 如果存在，就从缓存中拿}因为你要纠结它有外部依赖，同样是不加参数调用，连续两次的结果是不一样的，于是不纯。<br>为什么我一直不认同在中后台项目中使用React，原因就在这里，我反对的是整个业务应用的函数式倾向，很多人都是看到有很多好用的React组件，就会倾向于把它引入，然后，你知道怎么把自己的业务映射到函数式的那套理念上吗？函数式编程，无副作用，写出来的代码没有bug，这是真理没错，但是有两个问题需要考虑：1. JS本身，有太多特性与纯函数式的主张不适配，这一点，题叶能说得更多2. 业务系统里面的实体关系，如何组织业务逻辑，几十年来积累了无数的基于设计模式的场景经验，有太多的东西可以模仿，但是，没有人给你总结那么多如何把你的厚重业务映射到函数式理念的经验，这个地方很考验综合水平的，真的每个人都有能力去做这种映射吗？函数式编程无bug的根本就在于要把业务逻辑完全都依照这套理念搞好，你看看自己公司做中后台的员工，他们熟悉的是什么？是基于传统OO设计模式的这套东西，他们以为拿着你们给的组件库就得到了一切，但是可能还要被灌输函数式编程的一整套东西，而且又没人告诉他们在业务场景下，如何规划业务模型、组织代码，还要求快速开发，怎么能快起来？所以我真是心疼这些人，他们要的只是组件库，却不得不把业务逻辑的思考方式也作转换，这个事情没有一两年时间洗脑，根本洗不到能开发业务的程度。<br>没有好组件库的时候，大家痛点在视图层，有了基于React的组件化，把原先没那么痛的业务逻辑部分搞得也痛起来了，原先大家按照设计模式教的东西，照猫画虎还能继续开发了，学了一套新理念之后，都不知道怎么写代码了，怎么写都怀疑自己不对，可怕。<br>我宁可支持Angular也不支持React的原因也就在此，Angular至少在业务逻辑这块没有软主张，能够跟OO设计模式那套东西配合得很好。<br>我面对过很多商务场景，都是前端很厚重的东西，不仅仅是管理控制台这种，这类东西里面，业务逻辑的占比要比视图大挺多的，如何组织这些东西，目前几个主流技术栈都没有解决方案，要靠业务架构师去摆平。<br>如果你的场景不是这么厚重的，只是简单管理控制台，那当我没说好了。<br>框架是不能解决业务问题的，只能作为工具，放在合适的人手里，合适的场景下。<br>现在我要说说为什么我这么支持Vue了，没什么，可能有些方面是不如React，不如Angular，但它是渐进的，没有强主张，你可以在原有大系统的上面，把一两个组件改用它实现，当jQuery用；也可以整个用它全家桶开发，当Angular用；还可以用它的视图，搭配你自己设计的整个下层用。<br>你可以在底层数据逻辑的地方用OO和设计模式的那套理念，也可以函数式，都可以，它只是个轻量视图而已，只做了自己该做的事，没有做不该做的事，仅此而已。<br>渐进式的含义，我的理解是：没有多做职责之外的事。  </p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>图片格式详解:PNG、JPEG、GIF、SVG</title>
      <link href="unclass/image-format/"/>
      <url>unclass/image-format/</url>
      
        <content type="html"><![CDATA[<section class="ouvJEz"><h1 class="_1RuRku">PNG、JPEG、GIF、SVG应该用哪个？</h1><div class="rEsl9f"><div class="s-dsoj"><span class="_3tCVn5"><i aria-label="ic-diamond" class="anticon"><svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><use xlink:href="#ic-diamond"></use></svg></i><span>0.674</span></span><time datetime="2016-10-13T13:49:27.000Z">2016.10.13 21:49:27</time><span>字数 1790</span><span>阅读 11501</span></div></div><article class="_2rhmJa"><h3>Beginning</h3><p>当我们构建网站或者开发App的时候，应当怎样选择使用图片的类型呢？<br>是简单的全部使用一种类型还是根据业务情形选择不同的图片类型呢？<br>每种类型的图片类型又有怎样的优点和缺点呢？</p><h3>Concepts</h3><p>图片呈现效果的异同跟以下两个因素有关：</p><p>首先，压缩分两派：<strong>无损压缩</strong>和<strong>有损压缩</strong>。</p><ul><li><strong>无损压缩</strong> ：能够使图片占用的存储空间变小，而且不会损害图片的质量。</li><li><strong>有损压缩</strong>：相对<strong>无损压缩</strong>会压缩的更狠一点，但是不可避免的会对图片质量产生损害。如果有损压缩的次数多了的话，那么图片的质量也会越来越差。</li></ul><p>其次也有不同的色彩深度（色彩模式）：<strong>索引色彩</strong>和<strong>直接色彩</strong>。</p><ul><li><strong>索引色彩</strong> ：这个模式下图片仅可以存储有限数量的颜色种类（通常是2^8即256种）。</li><li><strong>直接色彩</strong>：这个模式下你可以存储成千上万种颜色值，所以相对而言采用这种模式的图片会显得色彩更加丰富饱满和艳丽。</li></ul><p>接下来会通过这两个维度对常见的几种图片类型来进行分析和比较，总结它们的优缺点和适用场景。</p><h3>BMP - 无损压缩、索引色彩模式、直接色彩模式</h3><p>这是较早出现的一种图片格式。它是无损的但是压缩比例着实很低，BMP格式的图片通常会占用较大的存储空间。它拥有两种色彩模式，但是由于占用存储空间如此之大，几乎没有人会去使用这种格式。<br>擅长：真的没有，BMP格式真的没有任何优点，大家还是尽量不要用这种格式的图片。</p><h3>GIF - 无损压缩、直接色彩模式</h3><p>GIF使用了更好的无损压缩算法，所以你可以压缩图片的大小但是不会丢失任何数据，文件大小也比BMP小得多。但是只可以使用索引色彩模式。这意味着大多数情况下最多只可以有256种颜色显示在图片里。颜色种类貌似真的好少，确实。GIF图片可以动并且拥有透明度（<code>透明或不透明，并没有alpha通道</code>）。<br>擅长：logo，线条，或其他需要尺寸尽可能小的简单图像。</p><h3>JPEG - 有损压缩、直接色彩模式</h3><p>JPEG是一种偏向平衡性的格式，它会舍弃掉人眼根本无法感知的颜色信息，以使文件尽可能小并且细节不丢失。因此，它是一种有损格式。它颜色丰富并且很适合那些允许轻微失真的像素色彩丰富的图片（如相片）。但是有损压缩意味着不适合logo和线图，因为不仅看起来模糊还比GIF占用的文件大小大。<br>擅长：相片，渐变图像。</p><h3>PNG-8 - 无损压缩、索引色彩模式</h3><p>PNG是一种较新的格式，并且PNG-8（PNG的索引模式版本）是GIF格式很好的替代。可是也有一些缺点：首先不能像GIF一样能动，其次对一些老旧的浏览器（如IE6）会有不兼容的问题。<br>擅长：PNG-8相对于GIF来讲有对alpha透明通道的支持。</p><h3>PNG-24 - 无损压缩、直接色彩模式</h3><p>PNG-24对无损压缩和直接色彩模式结合的很好（就像JPEG一样色彩丰富），在这方面和BMP很相似，但是PNG的压缩比率远强过BMP，所以文件大小也更小。不幸的是PNG-24仍然会比JPEG，GIF，PNG-8占用更多的存储空间，所以如果你对文件大小很在意的话，还是要考虑是否要选择以上的一种。</p><p>尽管PNG-24压缩比率较高而且还有丰富的色彩，但它不是为了来取代JPEG的，因为一个照片保存为PNG-24格式的话会比JPEG至少大5倍，但是图片显示质量却几乎没有提升。（如果你唯一考虑的因素就是图片质量的话，你还是可以使用这个格式的）<br>PNG-24和PNG-8一样也支持alpha透明通道。</p><h3>SVG -无损压缩、矢量模式</h3><p>SVG正变得越来越热门，它不同于以上所有的文件类型，因为它是一个矢量文件格式。这就是说它实际上是由线条和曲线，而不是像素组成的。当你放大一个矢量图像时，你仍然看到一条曲线或一条线。当你放大一个由像素构成的图像时，你会看到像素。<br>例如：</p><br><div class="image-package"><div class="image-container" style="max-width: 640px; max-height: 352px; background-color: transparent;"><div class="image-container-fill" style="padding-bottom: 55.00000000000001%;"></div></div><div class="image-caption"></div></div><br><div class="image-package"><div class="image-container" style="max-width: 640px; max-height: 352px; background-color: transparent;"><div class="image-container-fill" style="padding-bottom: 55.00000000000001%;"></div><div class="image-view" data-width="640" data-height="352"><img data-original-src="//upload-images.jianshu.io/upload_images/174711-b2a169cc588490f6.png" data-original-width="640" data-original-height="352" data-original-format="image/png" data-original-filesize="18743" data-image-index="1" class="" style="cursor: zoom-in;" src= "/img/loading.gif" data-lazy-src="//upload-images.jianshu.io/upload_images/174711-b2a169cc588490f6.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp"></div></div><div class="image-caption"></div></div><p>这意味着，对于小logo和图标和来说，SVG是很理想的，因为无论是Retina屏幕或在其他低清晰度的屏幕上它的形状都是一样的。这也意味着一个小的SVG logo可以放大但不失真，如果是像素构成的图片格式的话就需要设计多套图片，可以参考Android中的xxxdpi。<br>SVG文件的大小通常是极小的，即使它们看起来的样子真的很大。然而，值得注意的是，SVG文件的大小也取决于要展示图形的复杂度。而且SVG在渲染的时候需要比像素图更多的计算能力，这也就意味着性能的损耗。如果你的logo是特别复杂的，它可能会很耗费性能，甚至文件大小也非常大。所以尽可能简化你的矢量形状的复杂度是很重要也很有必要的。<br>此外，SVG文件是用XML编写的，因此可以在文本编辑器中打开和编辑。这意味着它展示的效果在运行时是可以改变的。例如，你可以使用JavaScript来改变对一个网站的SVG图标的颜色。所以，对于简单的平面形状，像logo或图形，使用svg是坠好的。<br>另外Android现在对SVG的支持也算是比较成熟了，微信团队貌似现在所有的图片资源都替换成SVG了。</p><h3>Summary</h3><p>所以这么一个小小的问题也有这么多值得挖掘的知识点。作为一个合格的工程师，任何一个细节都不可以放过，因为<code>They just make it better</code>.</p></article><div></div><div class="_1kCBjS"><div class="_18vaTa"><div class="_3BUZPB"><div class="_2Bo4Th" role="button" tabindex="-1" aria-label="给文章点赞"><i aria-label="ic-like" class="anticon"><svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><use xlink:href="#ic-like"></use></svg></i></div><span class="_1LOh_5" role="button" tabindex="-1" aria-label="查看点赞列表">16人点赞<i aria-label="icon: right" class="anticon anticon-right"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></div><div class="_3BUZPB"><div class="_2Bo4Th" role="button" tabindex="-1"><i aria-label="ic-dislike" class="anticon"><svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><use xlink:href="#ic-dislike"></use></svg></i></div></div></div><div class="_18vaTa"><a class="_3BUZPB _1x1ok9 _1OhGeD" href="/nb/359801" target="_blank" rel="noopener noreferrer"><i aria-label="ic-notebook" class="anticon"><svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><use xlink:href="#ic-notebook"></use></svg></i><span>日记本</span></a><div class="_3BUZPB ant-dropdown-trigger"><div class="_2Bo4Th"><i aria-label="ic-others" class="anticon"><svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><use xlink:href="#ic-others"></use></svg></i></div></div></div></div><div class="_19DgIp" style="margin-top:24px;margin-bottom:24px"></div><div class="_3W59v5"><div class="Uz-vZq"><div class="VwEQ52"><a class="_1OhGeD" href="/u/9b40ae19f574" target="_blank" rel="noopener noreferrer"><img class="_3nYIo3" src= "/img/loading.gif" data-lazy-src="//upload.jianshu.io/users/upload_avatars/174711/4a2fedd6424e?imageMogr2/auto-orient/strip|imageView2/1/w/120/h/120/format/webp" alt="  "></a><div class="_2lfNuF"><div class="Cqpr1X" title="lchad"><a class="_1OhGeD" href="/u/9b40ae19f574" target="_blank" rel="noopener noreferrer">lchad</a></div><div class="_2qBui4"><span>拥有1钻 (约0.35元)</span></div></div><button data-locale="zh-CN" type="button" class="_1OyPqC _3Mi9q9"><span>关注</span></button></div><div class="VwEQ52 _13lIbp"><div class="_2lfNuF"><div class="Cqpr1X">"小礼物走一走，来简书关注我"</div></div><button type="button" class="_1OyPqC _3Mi9q9"><span>赞赏</span></button></div></div></div></section>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>sublime Text 正则替换</title>
      <link href="front/quickly/sublime-regex/"/>
      <url>front/quickly/sublime-regex/</url>
      
        <content type="html"><![CDATA[<p><a href="https://cloud.tencent.com/developer/article/1342450">原文链接</a></p><div class="c-markdown J-articleContent"><p>我遇到一个文章，需要把所有的 (数字)  换为 [数字]</p><p>于是我使用 Sublime Text的替换</p><p>首先，我们需要打开正则使用“Alt+R” 或打开“Ctrl+h”选择正则。</p><p>然后我们开始输入正则，“ ((\d+) ” 我们需要拿出的是数字，所有在数字加“()”。于是在替换写“[$1]”，其中$0就是所有的，$1就是第一个括号。</p><p>如何使用正则可以去看<a data-from="10680" href="http://lindexi.oschina.io/lindexi/post/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F30%E5%88%86%E9%92%9F%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B/" target="_blank" rel="nofollow noopener noreferrer">正则表达入门</a>。</p><p>Sumlime 还可以创建代码行，做法也很简单。</p><p>点击 Tools   New Snippet</p><figure><div class="image-block"><span><img src= "/img/loading.gif" data-lazy-src="https://ask.qcloudimg.com/http-save/yehe-2759138/w41nf9yxc1.jpeg?imageView2/2/w/1620" class="" style="cursor: zoom-in;"></span></div></figure><pre class="prism-token token  language-javascript"><span class="token operator">&lt;</span> snippet<span class="token operator">&gt;</span>    <span class="token operator">&lt;</span> content<span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">!</span><span class="token punctuation">[</span>CDATA<span class="token punctuation">[</span>Hello<span class="token punctuation">,</span> $<span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token keyword">this</span><span class="token punctuation">}</span> is a $<span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">:</span>snippet<span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span> <span class="token operator">/</span>content<span class="token operator">&gt;</span>    <span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span> Optional<span class="token punctuation">:</span> Set a tabTrigger to define how to trigger the snippet <span class="token operator">--</span><span class="token operator">&gt;</span>    <span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span> <span class="token operator">&lt;</span>tabTrigger<span class="token operator">&gt;</span>hello<span class="token operator">&lt;</span><span class="token operator">/</span>tabTrigger<span class="token operator">&gt;</span> <span class="token operator">--</span><span class="token operator">&gt;</span>    <span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span> Optional<span class="token punctuation">:</span> Set a scope to limit where the snippet will trigger <span class="token operator">--</span><span class="token operator">&gt;</span>    <span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span> <span class="token operator">&lt;</span>scope<span class="token operator">&gt;</span>source<span class="token punctuation">.</span>python<span class="token operator">&lt;</span><span class="token operator">/</span>scope<span class="token operator">&gt;</span> <span class="token operator">--</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span> <span class="token operator">/</span>snippet<span class="token operator">&gt;</span></pre><p>content 是我们按下快捷键的内容，$ {1:this} 就是第一个输入内容，其中，默认写This，所有的{1}都代换你输入的第一个。$2就是第二个。</p><p>我们需要设置快捷键。</p><p><code>&lt;tabTrigger&gt;hello&lt;/tabTrigger&gt;</code></p><p>就是按下 hello，按下 tab 就会使用代码段。</p><p>写好，我们保存在<code>C:\Users\&lt;Use&gt;\AppData\Roaming\Sublime Text 2\Packages\User</code> 后缀<code>.sublime-snippet</code></p><p>我们有时打开中文会乱码，我们可以 ctrl+shift+p</p><p>输入 Package  control:install 安装 CovertToUTF8</p><figure><hr></figure></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> sublime </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>CSS中id与class 命名规则及编码的6个最佳习惯</title>
      <link href="front/standard/html-css-name-habit/"/>
      <url>front/standard/html-css-name-habit/</url>
      
        <content type="html"><![CDATA[<h3 id="一、用class-name方式写类名"><a href="#一、用class-name方式写类名" class="headerlink" title="一、用class_name方式写类名"></a>一、用class_name方式写类名</h3><p>以前喜欢用class-name写，不过好像两样也没什么差别。但我比较反对用className写类名，因为始终对浏览器大小写敏感的问题抱有怀疑态度。但是id我会写成驼峰式，理由见下一条。  </p><h3 id="二、样式都用class而不用id"><a href="#二、样式都用class而不用id" class="headerlink" title="二、样式都用class而不用id"></a>二、样式都用class而不用id</h3><p>有三个理由。  </p><p>1，id不可以重复，所以用class的话，可以肆无忌惮的用无数次。  </p><p>2，id的优先级太高，若是写了一个#page_contenta{color:#f60}，那你完蛋了，里面要改链接颜色，都必须加上#page_content才能越过这个优先级。  </p><p>3，id专门留给JS用，这样才符合表现与行为分离的原则。所以id我用驼峰式，也是为了体现这一点。  </p><h3 id="三、margin和padding，尽量省略最后一个值"><a href="#三、margin和padding，尽量省略最后一个值" class="headerlink" title="三、margin和padding，尽量省略最后一个值"></a>三、margin和padding，尽量省略最后一个值</h3><p>比如margin:20px10px5px10px;，左右值是一样的，就应该省略掉最后一个值，写成margin:20px10px5px;这样到时候要改左右间距，改一个就好，免得改漏了。其实这个问题虽然很细小，但是可以看得出对margin四个值省略规则的熟练程度。  </p><h3 id="四、按标准写css，再针对特定浏览器作hack"><a href="#四、按标准写css，再针对特定浏览器作hack" class="headerlink" title="四、按标准写css，再针对特定浏览器作hack"></a>四、按标准写css，再针对特定浏览器作hack</h3><p>比如，通常我们会遇到如下的写法：  </p><h3 id="ExampleSourceCode"><a href="#ExampleSourceCode" class="headerlink" title="ExampleSourceCode"></a>ExampleSourceCode</h3><pre><code>.side_col_52CSS&#123;    float:left;    display:inline;    margin-left:20px;    &#125;  </code></pre><p>而我的写法会是：  </p><h3 id="ExampleSourceCode-1"><a href="#ExampleSourceCode-1" class="headerlink" title="ExampleSourceCode"></a>ExampleSourceCode</h3><pre><code>.side_col_52CSS&#123;    float:left;    margin-left:20px;    &#125;    *.side_col_52CSS&#123;    _display:inline;/*hackedforIE6*/    &#125;  </code></pre><p>看明白了么？不应该把hack混在一起，也不应该用一种侥幸的心态，觉得float:left与display:inline写在一起没事。嗯，它们俩确实没事儿，但是其他的hack就不一定了。而且这里写display:inline纯粹就是为了解决IE6的bug，所以前面加上下划线，以明确的表达你的目的。  </p><p>另外不要以为凡是hack都是为IE准备的。其实有些hack是针对其他浏览器的，比如FF。这就要求你对css标准的熟练掌握，能够自信的判断哪些渲染是遵守标准，哪些违反标准的。<br>此外，我喜欢在hack前面加上星号，其实这纯粹是个人习惯了。可能过段时间我就不这么用了，呵呵。  </p><p>五、记得加空格  </p><p>.class_name{property:value;}。我个人觉得合理的空格是优秀代码的一个指标。按英文的习惯，标点后面都应该带空格（如果你写Thisisapen.That’sapencil.句点后面不加空格，word里面会有错误提示）。所以既然css是外国人发明的，应该按他们的格式来写。类似的，在JS里vara=b+c;里面的空格也应该都要加。  </p><p>六、适当的层叠（Cascading)或缩进以定义css的“作用域”  </p><p>什么是“css的作用域”？其实并不是所有的样式都在所有的地方使用。有的样式只用在某一块里面，比如“导航栏”里的“搜索框”，可能应该写成：  </p><p>ExampleSourceCode  </p><p>.nav .search{}<br>而有时候用层叠会增加代码优先级，所以也可以用缩进来“象征性的”体现作用域。像这样：  </p><p>ExampleSourceCode  </p><p>.login_box{}<br>.forgot_pwd{}<br>缩进，是为了表示它们对应的标签具有父子关系。但这样只能起一个提醒的作用。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> standard </tag>
            
            <tag> css </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>HTML，CSS的class与id命名规则</title>
      <link href="front/standard/html-css-name-standard/"/>
      <url>front/standard/html-css-name-standard/</url>
      
        <content type="html"><![CDATA[<h3 id="最重要的部分先说-命名书写格式"><a href="#最重要的部分先说-命名书写格式" class="headerlink" title="最重要的部分先说(命名书写格式)"></a>最重要的部分先说(命名书写格式)</h3><p>常见的格式有：连接符（search-btn）、下划线、全小（searchbox）、小驼峰（searchBox）。</p><p>现在用得多广泛的还是第一种使用连接符，易读、书写方便。</p><p>在这里小编<strong>推荐</strong>大家id使用下划线<code>_</code>来进行连接,class用中划线<code>-</code>来进行连接</p><h3 id="网页公共命名："><a href="#网页公共命名：" class="headerlink" title="网页公共命名："></a>网页公共命名：</h3><ul><li>#wrapper - - 页面外围控制整体布局宽度  </li><li>#container或#content - - 容器，用于最外层  </li><li>#layout -   -   布局  </li><li>#head，#header   -   -   页头部分  </li><li>#foot，#footer   -   -   页脚部分  </li><li>#nav    -   -   主导航  </li><li>#subnav -   -   二级导航  </li><li>#menu   -   -   菜单  </li><li>#submenu    -   -   子菜单  </li><li>#sidebar    -   -   侧栏  </li><li>#sidebar_a,#sidebar_b   -   -   左边栏或右边栏  </li><li>#main   -   -   页面主体  </li><li>#tag    -   -   标签  </li><li>#msg，#message   -   -   提示信息  </li><li>#tips   -   -   小技巧  </li><li>#vote   -   -   投票  </li><li>#friendlink -   -   友情链接  </li><li>#title  -   -   标题  </li><li>#summary    -   -   摘要  </li><li>#loginbar   -   -   登录条  </li><li>#searchInput    -   -   搜索输入框  </li><li>#hot    -   -   热门热点  </li><li>#search -   -   搜索  </li><li>#search_output  -   -   搜索输出和搜索结果相似  </li><li>#searchBar  -   -   搜索条  </li><li>#search_results -   -   搜索结果  </li><li>#copyright  -   -   版权信息  </li><li>#branding   -   -   商标  </li><li>#logo   -   -   网站LOGO标志  </li><li>#siteinfo   -   -   网站信息  </li><li>#siteinfoLegal  -   -   法律声名  </li><li>#siteinfoCredits    -   -   信誉  </li><li>#joinus -   -   加入我们  </li><li>#partner    -   -   合作伙伴  </li><li>#service    -   -   服务  </li><li>#regsiter   -   -   注册  </li><li>arr/arrow   -   -   箭头  </li><li>#guild  -   -   指南  </li><li>#sitemap    -   -   网站地图  </li><li>#list   -   -   列表  </li><li>#homeepage  -   -   首页  </li><li>#subpage    -   -   二级页面子页面  </li><li>#tool，#toolbar  -   -   工具条  </li><li>#drop   -   -   下拉  </li><li>#dorpmenu   -   -   下拉菜单  </li><li>#status -   -   状态  </li><li>#scroll -   -   滚动  </li><li>.tab    -   -   标签页  </li><li>.left,.right,.center    -   -   居中、左、右  </li><li>.news   -   -   新闻  </li><li>.download   -   -   下载  </li><li>.banner -   -   广告条（顶部广告条）</li></ul><h3 id="电子贸易相关："><a href="#电子贸易相关：" class="headerlink" title="电子贸易相关："></a>电子贸易相关：</h3><ul><li>.products - - 产品  </li><li>.products_prices  -   -   产品价格  </li><li>.products_description -   -   产品描述  </li><li>.products_review  -   -   产品评论  </li><li>.editor_review    -   -   编辑评论  </li><li>.news_release -   -   最新产品  </li><li>.publisher    -   -   生产商  </li><li>.screenshot   -   -   缩略图  </li><li>.faqs -   -   常见问题  </li><li>.keyword  -   -   关键词  </li><li>.blog -   -   博客  </li><li>.forum    -   -   论坛</li></ul><h3 id="基础的命名："><a href="#基础的命名：" class="headerlink" title="基础的命名："></a>基础的命名：</h3><ul><li>外套 wrap - - 用于最外层  </li><li>头部 header - - 用于头部  </li><li>主要内容 main - - 用于主体内容（中部）  </li><li>左侧 main-left - - 左侧布局  </li><li>右侧 main-right - - 右侧布局  </li><li>导航条 nav - - 网页菜单导航条  </li><li>内容 content - - 用于网页中部主体  </li><li>底部 footer - - 用于底部</li></ul><h3 id="CSS文件命名："><a href="#CSS文件命名：" class="headerlink" title="CSS文件命名："></a>CSS文件命名：</h3><ul><li>master.css,style.css  -   -   主要的  </li><li>module.css    -   -   模块  </li><li>base.css  -   -   基本共用  </li><li>layout.css    -   -   布局，版面  </li><li>themes.css    -   -   主题  </li><li>columns.css   -   -   专栏  </li><li>font.css  -   -   文字、字体  </li><li>forms.css -   -   表单  </li><li>mend.css  -   -   补丁  </li><li>print.css -   -   打印</li></ul><p><a href="https://www.freexyz.cn/dev/1303da806f11ee65093a2542fcab6c45.html">原文链接</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
            <tag> standard </tag>
            
            <tag> css </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jQ动画效果大全</title>
      <link href="front/jquery/jq-animation/"/>
      <url>front/jquery/jq-animation/</url>
      
        <content type="html"><![CDATA[<div class="htmledit_views" id="content_views">                                            <div style="line-height:1.75;"><strong><span style="font-size:24px;">一、show()方法和hide()方法</span></strong></div><div style="line-height:1.75;font-size:14px;"><span style="font-weight:bold;">1.show()与hide()</span></div><div style="line-height:1.75;"><span style="font-size:10px;">show()：根据hide()方法记住的display属性值来显示元素。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">hide() &nbsp; : 将该元素的display样式改为 "none"。</span></div><div style="line-height:1.75;font-size:14px;"><img src= "/img/loading.gif" data-lazy-src="" alt="" style="font-size:12px;"><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171220040927323" alt=""></div><div style="line-height:1.75;font-size:14px;"><span style="font-weight:bold;">2.参数让元素动起来：</span></div><div style="line-height:1.75;"><span style="font-size:10px;">单纯的调用show()和hide()相当于css("display","none/block/inline"),不会有任何动画。如果希望调用元素慢慢显示/消失，则可以为show()/hide()方法指定一个速度参数.</span></div><div style="line-height:1.75;"><span style="font-size:10px;color:#ff0000;">参数：slow,normal,fast,数值（以毫秒为单位）</span></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-string">"element"</span>).show(<span class="hljs-string">"slow"</span>);     <span class="hljs-comment">//元素将在600毫秒内慢慢地显示出来</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-string">"element"</span>).show(<span class="hljs-string">"normal"</span>);   <span class="hljs-comment">//元素将在400毫秒内慢慢地显示出来</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-string">"element"</span>).show(<span class="hljs-string">"fast"</span>);     <span class="hljs-comment">//元素将在200毫秒内慢慢地显示出来</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-string">"element"</span>).hide(<span class="hljs-string">"1000"</span>);     <span class="hljs-comment">//元素将在1000毫秒(1秒)内慢慢地隐藏</span></div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre><span style="font-size:10px;color:#ff0000;">注：对元素使用带参数的show()和hide()是从：高度，宽度，不透明度 &nbsp;三个属性同时进行操作的。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">例如：若对一个&lt;div&gt;(矩形)使用hide(600)。hide(600)会同时减少"矩形"的高度、宽度和不透明度，直到3个属性的值都为0，最后设置该元素的CSS规则为"display:none"。同理show(600)则会从该元素上到下增加“矩形”高度，左到右增大“矩形”的宽度，同时增加“矩形”的不透明度，直至矩形完全显示出来。</span></div><div style="line-height:1.75;font-size:14px;"><br></div><div style="line-height:1.75;"><strong><span style="font-size:24px;">二、fadeIn()方法和fadeOut()方法</span></strong></div><div style="line-height:1.75;"><span style="font-size:10px;color:#ff0000;">fadeIn()/fadeOut() 只改变元素的不透明度。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">fadeOut() &nbsp; ：会在指定的一段时间内降低元素的不透明度，直到元素完全消失("display:none")。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">fadeIn() &nbsp; &nbsp; &nbsp;：与fadeOut()完全相反。</span></div><div style="line-height:1.75;"><span><span style="font-size:10px;">例：</span></span></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-string">"#panel h5.head"</span>).toggle(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-keyword">this</span>).next(<span class="hljs-string">"div.content"</span>).fadeOut();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-keyword">this</span>).next(<span class="hljs-string">"div.content"</span>).fadeIn();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre></div><div style="line-height:1.75;font-size:14px;"><span style="font-size:12px;color:rgb(51,51,51);"><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171220040829803" alt=""></span></div><div style="line-height:1.75;font-size:14px;"><span style="font-size:12px;color:rgb(51,51,51);"><br></span></div><div><img src= "/img/loading.gif" data-lazy-src="" alt=""></div><div style="line-height:1.75;"><strong><span style="font-size:24px;">三、slideUp()方法和slideDown()方法</span></strong></div><div style="line-height:1.75;"><span style="font-size:10px;color:#ff0000;">slideUp()/slideDown()只改变元素的高度。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">slideDown()：如果一个元素的display属性值为"none"，当调用slideDown()时，这个元素将由上至下延伸显示。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">slideUp() &nbsp; &nbsp; ：与slideDown()完全相反。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">例：</span></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-string">"#panel h5.head"</span>).toggle(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-keyword">this</span>).next(<span class="hljs-string">"div.content"</span>).slideUp();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-keyword">this</span>).next(<span class="hljs-string">"div.content"</span>).slideDown();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre><span style="font-size:10px;">效果如图：</span></div><div style="line-height:1.75;font-size:14px;"><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171220040805164" alt=""></div><div style="line-height:1.75;font-size:14px;"><br></div><div style="line-height:1.75;"><div style="line-height:1.75;"><strong><span style="font-size:24px;">四、自定义动画方法animate()</span></strong></div><div style="line-height:1.75;"><span style="color:rgb(227,0,0);"><span style="font-size:10px;">animate(params, speed ,callback);</span></span></div><div style="line-height:1.75;"><span style="font-size:10px;">参数说明：</span></div><div style="line-height:1.75;"><span style="font-size:10px;">（1）params： 一个包含样式属性及值的映射，比如{property1: "value1", property2: "value2", ····· }</span></div><div style="line-height:1.75;"><span style="font-size:10px;">（2）speed &nbsp; &nbsp;: 速度参数，可选。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">（3）callback:在动画完成时执行的函数，可选。</span></div><div style="font-size:14px;line-height:1.75;"><span style="font-weight:bold;">1.自定义简单动画</span></div><div style="line-height:1.75;"><span style="font-size:10px;">例：当点击id="panel"的&lt;div&gt;时，该div就会向右运动。</span></div><div style="line-height:1.75;"><pre><code class="hljs xml"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css"></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-id">#panel</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">  <span class="hljs-attribute">position</span>:relative;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">  <span class="hljs-attribute">width</span>:<span class="hljs-number">100px</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">  <span class="hljs-attribute">height</span>:<span class="hljs-number">100px</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">  <span class="hljs-attribute">border</span>:<span class="hljs-number">1px</span> solid <span class="hljs-number">#0050D0</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"panel"</span>&gt;</span>click me<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-string">"#panel"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">          $(<span class="hljs-keyword">this</span>).animate(&#123;<span class="hljs-attr">left</span>:<span class="hljs-string">"500px"</span>&#125;,<span class="hljs-number">3000</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     &#125;);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre><span style="font-size:14px;"><strong>2.累加、累减动画</strong></span></div><div style="line-height:1.75;"><span style="font-size:10px;">将上例jQuery代码改为 &nbsp; (在500px之前加上"+="或"-="，即表示在当前位置累加或者类减)</span></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-string">"#panel"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">          $(<span class="hljs-keyword">this</span>).animate(&#123;<span class="hljs-attr">left</span>:<span class="hljs-string">"+=500px"</span>&#125;,<span class="hljs-number">3000</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     &#125;);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre><span style="font-size:14px;"><strong>3.多重动画</strong></span></div><div style="line-height:1.75;"><span style="font-size:10px;">（1）同时执行多个动画</span></div><div style="line-height:1.75;"><span style="font-size:10px;">例：元素向右滑动的同时，高度也在增加。</span></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-string">"#panel"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">          $(<span class="hljs-keyword">this</span>).animate(&#123;<span class="hljs-attr">left</span>:<span class="hljs-string">"500px"</span>，height:<span class="hljs-string">"200px"</span>&#125;,<span class="hljs-number">3000</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     &#125;);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre><span style="font-size:10px;">（2）按顺序执行多个动画</span></div><div style="line-height:1.75;"><span style="font-size:10px;">例：元素先向右滑动，然后再增加它的高度。</span></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-string">"#panel"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">          $(<span class="hljs-keyword">this</span>).animate(&#123;<span class="hljs-attr">left</span>:<span class="hljs-string">"500px"</span>&#125;,<span class="hljs-number">3000</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">          $(<span class="hljs-keyword">this</span>).animate(&#123;<span class="hljs-attr">height</span>:<span class="hljs-string">"200px"</span>&#125;,<span class="hljs-number">3000</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">          <span class="hljs-comment">//或者改写成 $(this).animate(&#123;left:"500px"&#125;,3000).animate(&#123;height:"200px"&#125;,3000);</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     &#125;);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre>注：像这样，动画效果的执行具有先后顺序，称为"动画队列"。</div><div style="font-size:14px;line-height:1.75;"><span style="font-weight:bold;">4.综合动画</span></div><div style="font-size:14px;line-height:1.75;"><span style="font-weight:bold;"><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171220042852742" alt=""></span></div><div style="font-size:14px;"><img src= "/img/loading.gif" data-lazy-src="" alt=""></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">$(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-string">"#panel"</span>).css(<span class="hljs-string">"opacity"</span>,<span class="hljs-string">"0.5"</span>); <span class="hljs-comment">//设置不透明度</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-string">"#panel"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">          $(<span class="hljs-keyword">this</span>).animate(&#123;<span class="hljs-attr">left</span>:<span class="hljs-string">"400px"</span>,<span class="hljs-attr">heigth</span>:<span class="hljs-string">"200px"</span>,<span class="hljs-attr">opacity</span>:<span class="hljs-string">"1"</span>&#125;,<span class="hljs-number">3000</span>)</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">                 .animate(&#123;<span class="hljs-attr">top</span>:<span class="hljs-string">"200px"</span>&#125;,<span class="hljs-number">3000</span>)</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">                 .fadeOut(<span class="hljs-string">"slow"</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     &#125;);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre><span style="font-size:14px;"><strong>5.动画回调函数</strong></span></div><div style="line-height:1.75;"><span style="font-size:14px;"><strong><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171220042916689" alt=""><br></strong></span></div><div style="font-size:14px;"><img src= "/img/loading.gif" data-lazy-src="" alt=""></div><div style="line-height:1.75;">代码如下<pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-string">"#panel"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">          $(<span class="hljs-keyword">this</span>).animate(&#123;<span class="hljs-attr">left</span>:<span class="hljs-string">"400px"</span>,<span class="hljs-attr">heigth</span>:<span class="hljs-string">"200px"</span>,<span class="hljs-attr">opacity</span>:<span class="hljs-string">"1"</span>&#125;,<span class="hljs-number">3000</span>)</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">                 .animate(&#123;<span class="hljs-attr">top</span>:<span class="hljs-string">"200px"</span>&#125;,<span class="hljs-number">3000</span>，<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">                         $(<span class="hljs-keyword">this</span>).css(<span class="hljs-string">"border"</span>,<span class="hljs-string">"5px solid blue"</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">                 &#125;)</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     &#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre><br></div><div style="line-height:1.75;"><strong><span style="font-size:24px;">五、停止动画和判断是否处于动画状态</span></strong></div><div style="line-height:1.75;"><strong>1.停止元素的动画</strong></div><div style="line-height:1.75;"><span style="font-size:10px;"><span style="color:#ff0000;">stop([clearQueue] [, gotoEnd])</span>&nbsp;&nbsp; :停止动画。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">参数clearQueue,gotoEnd都是可选参数，为Boolean值（ture或flase）。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">clearQueue代表是否清空未执行完的动画队列。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">gotoEnd代表是否直接将正在执行的动画跳转到末状态。</span></div><div style="line-height:1.75;"><span style="font-weight:bold;">2.判断元素是否处于动画状态</span></div><div style="line-height:1.75;"><strong><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171220042956032" alt=""><br></strong></div><div style="font-size:14px;"><img src= "/img/loading.gif" data-lazy-src="" alt=""></div><div style="line-height:1.75;"><span style="font-size:24px;"><strong>六、其他动画方法</strong></span></div><div style="line-height:1.75;"><span style="font-size:10px;">1.toggle(speed,[callback]) &nbsp; &nbsp; ：切换元素可见状态。如果元素是可见的，则切换为隐藏的；反之亦然。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">2.slideToggle(speed,[callback]) ：通过高度变化来切换元素的可见性。</span></div><div style="line-height:1.75;"><span style="font-size:10px;">3.fadeTo(speed, opacity, [callback]) ：把元素的不透明度以渐进方式调整到指定的值。</span></div><div style="line-height:1.75;"><span style="font-size:10px;"><br></span></div><div style="line-height:1.75;"><span style="font-size:10px;">1.toggle(speed,[callback])</span></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span style="font-size:10px;">$(<span class="hljs-string">"#panel h5.head"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-keyword">this</span>).next(<span class="hljs-string">"div.content"</span>).toggle();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre></div><div><span style="font-size:10px;"><img src= "/img/loading.gif" data-lazy-src="" alt=""></span></div><div style="line-height:1.75;"><span style="font-size:10px;">2.slideToggle(speed,[callback])</span><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span style="font-size:10px;">$(<span class="hljs-string">"#panel h5.head"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-keyword">this</span>).next(<span class="hljs-string">"div.content"</span>).slideToggle();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre></div><div><span style="font-size:10px;"><img src= "/img/loading.gif" data-lazy-src="" alt=""></span></div><div><span style="font-size:10px;"><img src= "/img/loading.gif" data-lazy-src="" alt=""></span></div><div style="line-height:1.75;"><span style="font-size:10px;">3.fadeTo(speed, opacity, [callback])</span></div><div style="line-height:1.75;"><pre><code class="hljs javascript"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span style="font-size:10px;">$(<span class="hljs-string">"#panel h5.head"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">     $(<span class="hljs-keyword">this</span>).next(<span class="hljs-string">"div.content"</span>).fadeTo(<span class="hljs-number">600</span>,<span class="hljs-number">0.2</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&#125;);</div></div></li></ol></code><div class="hljs-button signin" data-title="登录后复制" onclick="hljs.signin(event)"></div></pre></div></div><div style="line-height:1.75;"><strong><span style="font-size:24px;">七、动画方法概括</span></strong></div><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171220042648431" alt=""><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20171220042702579" alt=""><br>                                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>js 原型链的理解</title>
      <link href="front/js/js-prototype%20chain/"/>
      <url>front/js/js-prototype%20chain/</url>
      
        <content type="html"><![CDATA[<div class="project-body"><div class="portlet-title pro-title" style="width: 1220px;"><div class="set-btn-group font-settings pull-left"><a href="javascript:;" class="expand-collapse-trigger" title="折叠/展开"><i class="icon-th-list"></i></a><a href="javascript:;" class="toggle-dropdown" title="视觉主题设置"><i class="icon-font"></i></a><div class="set-dropdown-menu docblur" style="display:none;"><div class="dropdown-caret"><span class="caret-outer"></span><span class="caret-inner"></span></div><div class="buttons font-opt"><button class="button size font-reduce" font="reduce" title="缩小字体">A</button><button class="button size font-enlarge" font="enlarge" title="放大字体">A</button></div><div class="buttons bg-color"><button class="button theme" color="color-theme-white" title="默认模式">默认</button><button class="button theme" color="color-theme-sepia" title="护眼模式">护眼</button><button class="button theme" color="color-theme-night" title="夜间模式">夜间</button></div></div></div><div class="kn-btn-group pull-right">            <span id="content-head-viewcount" class="viewcount-btn"><i class="icon-eye-open"></i> <span>阅读(67243)</span></span><a id="knstar" href="javascript:;" onclick="isstar()" data-type="star"><i class="icon-bookmark-empty"></i> <span>书签</span></a><a class="btn-thumbs-up" href="javascript:;" onclick="islike()"><i class="icon-thumbs-up"></i> <span id="likestatus">赞</span>(<span id="likecount">6</span>)</a><a href="javascript:;" title="分享" class="share-btn  popup_more bdsharebuttonbox bdshare-button-style0-16" data-cmd="more" data-bd-bind="1568202163307"><i class="icon-share"></i> 分享</a><a href="/edit/javascript/javascript-5isn2lax" rel="nofollow"><i class="icon-edit"></i> <span>我要纠错</span></a></div></div><div id="pro-mian-header"><div class="content-top"><h1>JavaScript 原型链的理解</h1></div><div class="kn-infomation">由&nbsp;<span>alexbro</span>&nbsp;创建，Loen 最后一次修改&nbsp;<span>2018-02-24</span>    </div>          </div>          <div class="content-bg"><div class="content-intro view-box "><p>看这样一段代码：</p><pre lang="javascript" style="max-width: 100%;"><code class="javascript hljs"><span class="hljs-keyword">var</span> Person = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123; &#125;;<span class="hljs-keyword">var</span> p = <span class="hljs-keyword">new</span> Person();</code></pre><p>我们来看看这个 new 究竟做了什么？</p><blockquote><p>我们把 new 的过程拆分成以下三步：</p><p>1. var p={}; 也就是说，初始化一个对象p。</p><p>2. p.__proto__=Person.prototype;</p><p>3. Person.call(p);也就是说构造p，也可以称之为初始化p。</p></blockquote><p>我们来证明一下：</p><pre lang="javascript" style="max-width: 100%;" showdemo="1"><code class="javascript hljs"><span class="hljs-keyword">var</span> Person = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123; &#125;;<span class="hljs-keyword">var</span> p = <span class="hljs-keyword">new</span> Person();alert(p.__proto__ === Person.prototype); <span class="hljs-comment">// true</span></code></pre><p>这段代码会返回 true。说明我们步骤2是正确的。</p><p><br></p><p>那么__proto__是什么？</p><blockquote><p>每个对象都会在其内部初始化一个属性，就是 __proto__，当我们访问一个对象的属性 时，如果这个对象内部不存在这个属性，那么他就会去__proto__里找这个属性，这个__proto__又会有自己的__proto__，于是就这样 一直找下去，也就是我们平时所说的原型链的概念。</p></blockquote><p>按照标准，__proto__是不对外公开的，也就是说是个私有属性，但是 Firefox 的引擎将他暴露了出来成为了一个共有的属性，我们可以对外访问和设置。</p><p>我们看一下下面这些代码：</p><pre lang="javascript" style="max-width: 100%;" showdemo="1"><code class="javascript hljs"><span class="hljs-keyword">var</span> Person = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123; &#125;;&nbsp;&nbsp;&nbsp;&nbsp;Person.prototype.Say = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123;&nbsp;&nbsp;&nbsp;&nbsp;alert(<span class="hljs-string">"Person say"</span>);&#125;<span class="hljs-keyword">var</span> p = <span class="hljs-keyword">new</span> Person();p.Say();</code></pre><p>我们看下为什么 p 可以访问 Person 的 Say。</p><p>首先var p=new Person()；</p><p>可以得出 p.__proto__=Person.prototype。那么当我们调用 p.Say() 时，首先 p 中没有 Say 这个属性， 于是，他就需要到他的 __proto__ 中去找，也就是 Person.prototype，而我们在上面定义了 Person.prototype.Say = function(){}; 于是，就找到了这个方法。</p><p>好，接下来，让我们看个更复杂的。</p><p><br></p><p>我们来做这样的推导：</p><p>var p=new Programmer()可以得出p.__proto__=Programmer.prototype;</p><p>而在上面我们指定了Programmer.prototype=new Person();我们来这样拆分，var p1=new Person();Programmer.prototype=p1;那么:</p><p>p1.__proto__=Person.prototype;</p><p>Programmer.prototype.__proto__=Person.prototype;</p><p>由根据上面得到p.__proto__=Programmer.prototype。可以得到p.__proto__.__proto__=Person.prototype。</p><p>好，算清楚了之后我们来看上面的结果,p.Say()。由于p没有Say这个属性，于是去p.__proto__，也就是 Programmer.prototype，也就是p1中去找，由于p1中也没有Say，那就去p.__proto__.__proto__，也就是 Person.prototype中去找，于是就找到了alert(“Person say”)的方法。</p><p>其余的也都是同样的道理。</p><p>这也就是原型链的实现原理。</p><p>最后，其实prototype只是一个假象，他在实现原型链中只是起到了一个辅助作用，换句话说，他只是在new的时候有着一定的价值，而原型链的本质，其实在于__proto__！</p><p><br></p></div><div style="clear:both"></div></div><!--控制本地字体主题样式--><script type="text/javascript">var tempFontsize = $.cookie("fontsize");if (tempFontsize != undefined) {$("#pro-mian").addClass(tempFontsize);}</script><!--我要赞赏--><div class="project-sq"><div class="project-sq-info"><span>您的支持将鼓励我们做得更好</span></div><ul class="project-sq-avatar"></ul><div class="project-sq-btnarea"><a href="javascript:;">赞赏支持</a></div></div><!--我要赞赏结束--><!--我要评价--><div id="evaluate-box"><span id="evaluates">以上内容是否对您有帮助：</span><span class="star_score"><span title="1分"></span><span title="2分"></span><span title="3分"></span><span title="4分"></span><span title="5分"></span></span></div><!--评价结束--><div class="content-links"><div class="previous-link">← <a href="/javascript/javascript-expression.html" title="上一篇：javascript正则表达式知识拓展总结">javascript正则表达式知识拓展总结</a></div></div><!--练习、出题、写笔记--><div class="project-operation"><div class="pull-right"><a href="javascript:;" class="op-btn note-btn" onclick="openNote()"><i class="icon-pencil"></i>写笔记</a></div></div><!--横版广告放置--><div class="abox-item">    <div class="abox-content">    </div></div> <!-- 笔记列表 --><div class="notelist-box" style="display:none"><div class="notelist-head" onclick="openNoteList(this)"><span class="notelist-title">精选笔记</span><i class="icon-circle-arrow-up"></i></div><div class="notelist-content" id="notelist_content" style="display: none;"></div></div><!--相关推荐|wiki推荐--><div class="maylike"><h2 class="project-maylike-info">您可能还喜欢：</h2><ul class="project-maylike-ul"><li><a href="/javascript/javascript-t64x2ksc.html" title="JavaScript JSON.stringify()">JavaScript JSON.stringify()</a></li><li><a href="/javascript/js-typeof.html" title="JavaScript typeof, null, 和 undefined">JavaScript typeof, null, 和 undefined</a></li></ul></div><!--相关推荐|wiki推荐 结束--></div>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Emmet的html语法</title>
      <link href="front/quickly/emmet-html-grammer/"/>
      <url>front/quickly/emmet-html-grammer/</url>
      
        <content type="html"><![CDATA[<p><strong>所有操作按下“tab”键即可瞬间完成</strong></p><h3 id="元素"><a href="#元素" class="headerlink" title="元素"></a>元素</h3><p>1.在编辑器中输入元素名称，即可自动补全生成 HTML 标签，即使不是标准的 HTML 标签。<br>2.输入：! 或者 html:5 或者 html:4s 或者 html:4t 将自动补全html基本结构</p><h3 id="嵌套操作"><a href="#嵌套操作" class="headerlink" title="嵌套操作"></a>嵌套操作</h3><p>1.使用“&gt;”生成子元素</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">div&gt;ul&gt;li</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;div&gt;</span><br><span class="line">    &lt;ul&gt;</span><br><span class="line">        &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">    &lt;&#x2F;ul&gt;</span><br><span class="line">&lt;&#x2F;div&gt;</span><br></pre></td></tr></table></figure><p>2.使用“+”生成兄弟元素</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">div+p+bq</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;div&gt;&lt;&#x2F;div&gt;</span><br><span class="line">&lt;p&gt;&lt;&#x2F;p&gt;</span><br><span class="line">&lt;blockquote&gt;&lt;&#x2F;blockquote&gt;</span><br></pre></td></tr></table></figure><p>3.使用“^”生成父元素</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">div+div&gt;p&gt;span+em^bq</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;div&gt;&lt;&#x2F;div&gt;</span><br><span class="line">&lt;div&gt;</span><br><span class="line">    &lt;p&gt;&lt;span&gt;&lt;&#x2F;span&gt;&lt;em&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;</span><br><span class="line">    &lt;blockquote&gt;&lt;&#x2F;blockquote&gt;</span><br><span class="line">&lt;&#x2F;div&gt;</span><br></pre></td></tr></table></figure><p>4.使用“*”生成多个相同元素</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">div&gt;ul&gt;li*5</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;div&gt;</span><br><span class="line">    &lt;ul&gt;</span><br><span class="line">        &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">        &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">        &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">        &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">        &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">    &lt;&#x2F;ul&gt;</span><br><span class="line">&lt;&#x2F;div&gt;</span><br></pre></td></tr></table></figure><p>5.使用“()”将元素分组</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">&#x2F;&#x2F; &quot;+&quot; 后面的元素与括号中的第一个元素属于兄弟关系</span><br><span class="line">div&gt;(header&gt;ul&gt;li*2)+footer&gt;p</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;按下TAB键</span><br><span class="line">&lt;div&gt;</span><br><span class="line">    &lt;header&gt;</span><br><span class="line">        &lt;ul&gt;</span><br><span class="line">            &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">            &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">        &lt;&#x2F;ul&gt;</span><br><span class="line">    &lt;&#x2F;header&gt;</span><br><span class="line">    &lt;footer&gt;</span><br><span class="line">        &lt;p&gt;&lt;&#x2F;p&gt;</span><br><span class="line">    &lt;&#x2F;footer&gt;</span><br><span class="line">&lt;&#x2F;div&gt;</span><br></pre></td></tr></table></figure><h3 id="属性操作"><a href="#属性操作" class="headerlink" title="属性操作"></a>属性操作</h3><p>1.id与class：元素与 id 属性值之间用 “#” 分隔，与 class 属性值之间用 “.” 分隔</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">div#header+div.page+div#footer.class1.class2.class3</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;div id&#x3D;&quot;header&quot;&gt;&lt;&#x2F;div&gt;</span><br><span class="line">&lt;div class&#x3D;&quot;page&quot;&gt;&lt;&#x2F;div&gt;</span><br><span class="line">&lt;div id&#x3D;&quot;footer&quot; class&#x3D;&quot;class1 class2 class3&quot;&gt;&lt;&#x2F;div&gt;</span><br></pre></td></tr></table></figure><p>2.使用“[]”标记其他属性</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">td[title&#x3D;&#39;hello&#39; colspan&#x3D;3]</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;td title&#x3D;&quot;hello&quot; colspan&#x3D;&quot;3&quot;&gt;&lt;&#x2F;td&gt;</span><br></pre></td></tr></table></figure><p>3.用“$”符号实现1到n的自动编号（“*”实现多个元素）</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">li.item$*3</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;li class&#x3D;&quot;item1&quot;&gt;&lt;&#x2F;li&gt;</span><br><span class="line">&lt;li class&#x3D;&quot;item2&quot;&gt;&lt;&#x2F;li&gt;</span><br><span class="line">&lt;li class&#x3D;&quot;item3&quot;&gt;&lt;&#x2F;li&gt;</span><br></pre></td></tr></table></figure><p>可在 “$” 后添加 “@n” 修改编号的起始值为n。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">li.item$@3*3</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;li class&#x3D;&quot;item3&quot;&gt;&lt;&#x2F;li&gt;</span><br><span class="line">&lt;li class&#x3D;&quot;item4&quot;&gt;&lt;&#x2F;li&gt;</span><br><span class="line">&lt;li class&#x3D;&quot;item5&quot;&gt;&lt;&#x2F;li&gt;</span><br></pre></td></tr></table></figure><p>可在 “$” 后添加 “@-” 修改编号的方向。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">li.item$@-3*3</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;li class&#x3D;&quot;item5&quot;&gt;&lt;&#x2F;li&gt;</span><br><span class="line">&lt;li class&#x3D;&quot;item4&quot;&gt;&lt;&#x2F;li&gt;</span><br><span class="line">&lt;li class&#x3D;&quot;item3&quot;&gt;&lt;&#x2F;li&gt;</span><br></pre></td></tr></table></figure><p>4.用“{}”添加文本内容</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 输入</span><br><span class="line">a[href&#x3D;me.htm]&#123;click me&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 按下TAB键</span><br><span class="line">&lt;a href&#x3D;&quot;me.htm&quot;&gt;click me&lt;&#x2F;a&gt;</span><br></pre></td></tr></table></figure><p>更多简写方法不断更新中，关注我即可获取最新消息哦～</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> html </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>js、jq获取当前鼠标位置</title>
      <link href="front/jquery/jq-get-mouse-position/"/>
      <url>front/jquery/jq-get-mouse-position/</url>
      
        <content type="html"><![CDATA[<h3 id="使用jQuery获取"><a href="#使用jQuery获取" class="headerlink" title="使用jQuery获取"></a>使用jQuery获取</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;Content-Type&quot;</span> <span class="attr">content</span>=<span class="string">&quot;text/html; charset=gb2312&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>javascript获得鼠标位置<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;js/jquery.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span> <span class="attr">id</span>=<span class="string">&quot;testDiv&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span></span><br><span class="line"><span class="javascript">    $(<span class="string">&#x27;#testDiv&#x27;</span>).mousemove(<span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">var</span> xx = e.originalEvent.x || e.originalEvent.layerX || <span class="number">0</span>;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">var</span> yy = e.originalEvent.y || e.originalEvent.layerY || <span class="number">0</span>;</span></span><br><span class="line"><span class="javascript">        $(<span class="built_in">this</span>).text(xx + <span class="string">&#x27;---&#x27;</span> + yy);</span></span><br><span class="line"><span class="javascript">        <span class="comment">//var d = document.getElementById(&quot;div&quot;);获取某div在当前窗口的位置</span></span></span><br><span class="line"><span class="javascript">        <span class="comment">//var dx = xx - p.getBoundingClientRect().left;</span></span></span><br><span class="line"><span class="javascript">        <span class="comment">//var dy = yy - p.getBoundingClientRect().top;</span></span></span><br><span class="line"><span class="javascript">        <span class="comment">//$(this).text(dx + &#x27;---&#x27; + dy);鼠标在该div内位置</span></span></span><br><span class="line">    &#125;);</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="使用JavaScript获取"><a href="#使用JavaScript获取" class="headerlink" title="使用JavaScript获取"></a>使用JavaScript获取</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;Content-Type&quot;</span> <span class="attr">content</span>=<span class="string">&quot;text/html; charset=gb2312&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>javascript获得鼠标位置<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">鼠标X轴:</span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">id</span>=<span class="string">xxx</span> <span class="attr">type</span>=<span class="string">text</span>&gt;</span></span><br><span class="line">鼠标Y轴:</span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">id</span>=<span class="string">yyy</span> <span class="attr">type</span>=<span class="string">text</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">mouseMove</span>(<span class="params">ev</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        Ev = ev || <span class="built_in">window</span>.event;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">var</span> mousePos = mouseCoords(ev);</span></span><br><span class="line"><span class="javascript">        <span class="built_in">document</span>.getElementById(<span class="string">&quot;xxx&quot;</span>).value = mousePos.x;</span></span><br><span class="line"><span class="javascript">        <span class="built_in">document</span>.getElementById(<span class="string">&quot;yyy&quot;</span>).value = mousePos.y;</span></span><br><span class="line">    &#125;</span><br><span class="line"><span class="javascript">    <span class="function"><span class="keyword">function</span> <span class="title">mouseCoords</span>(<span class="params">ev</span>) </span>&#123;</span></span><br><span class="line">        if (ev.pageX || ev.pageY) &#123;</span><br><span class="line"><span class="javascript">            <span class="keyword">return</span> &#123;<span class="attr">x</span>: ev.pageX, <span class="attr">y</span>: ev.pageY&#125;;</span></span><br><span class="line">        &#125;</span><br><span class="line"><span class="javascript">        <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="javascript">            x: ev.clientX + <span class="built_in">document</span>.body.scrollLeft - <span class="built_in">document</span>.body.clientLeft,</span></span><br><span class="line"><span class="javascript">            y: ev.clientY + <span class="built_in">document</span>.body.scrollTop - <span class="built_in">document</span>.body.clientTop</span></span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="javascript">    <span class="built_in">document</span>.onmousemove = mouseMove;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>js中的事件委托和事件代理详解</title>
      <link href="front/js/js-event-advance/"/>
      <url>front/js/js-event-advance/</url>
      
        <content type="html"><![CDATA[<html> <head></head> <body>  <div id="cnblogs_post_body" class="blogpost-body ">    <h3>起因：</h3>   <p>1、这是前端面试的经典题型，要去找工作的小伙伴看看还是有帮助的；</p>    <p>2、其实我一直都没弄明白，写这个一是为了备忘，二是给其他的知其然不知其所以然的小伙伴们以参考；</p>    <h3>概述：</h3>   <p>那什么叫事件委托呢？它还有一个名字叫事件代理，JavaScript高级程序设计上讲：事件委托就是利用事件冒泡，只指定一个事件处理程序，就可以管理某一类型的所有事件。那这是什么意思呢？网上的各位大牛们讲事件委托基本上都用了同一个例子，就是取快递来解释这个现象，我仔细揣摩了一下，这个例子还真是恰当，我就不去想别的例子来解释了，借花献佛，我摘过来，大家认真领会一下事件委托到底是一个什么原理：</p>    <p>有三个同事预计会在周一收到快递。为签收快递，有两种办法：一是三个人在公司门口等快递；二是委托给前台MM代为签收。现实当中，我们大都采用委托的方案（公司也不会容忍那么多员工站在门口就为了等快递）。前台MM收到快递后，她会判断收件人是谁，然后按照收件人的要求签收，甚至代为付款。这种方案还有一个优势，那就是即使公司里来了新员工（不管多少），前台MM也会在收到寄给新员工的快递后核实并代为签收。</p>    <p>这里其实还有2层意思的：</p>    <p>第一，现在委托前台的同事是可以代为签收的，即程序中的现有的dom节点是有事件的；</p>    <p>第二，新员工也是可以被前台MM代为签收的，即程序中新添加的dom节点也是有事件的。</p>    <h3>为什么要用事件委托：</h3>   <p>一般来说，dom需要有事件处理程序，我们都会直接给它设事件处理程序就好了，那如果是很多的dom需要添加事件处理呢？比如我们有100个li，每个li都有相同的click点击事件，可能我们会用for循环的方法，来遍历所有的li，然后给它们添加事件，那这么做会存在什么影响呢？</p>    <p>在JavaScript中，添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能，因为需要不断的与dom节点进行交互，访问dom的次数越多，引起浏览器重绘与重排的次数也就越多，就会延长整个页面的交互就绪时间，这就是为什么性能优化的主要思想之一就是减少DOM操作的原因；如果要用事件委托，就会将所有的操作放到js程序里面，与dom的操作就只需要交互一次，这样就能大大的减少与dom的交互次数，提高性能；</p>    <p>每个函数都是一个对象，是对象就会占用内存，对象越多，内存占用率就越大，自然性能就越差了（内存不够用，是硬伤，哈哈），比如上面的100个li，就要占用100个内存空间，如果是1000个，10000个呢，那只能说呵呵了，如果用事件委托，那么我们就可以只对它的父级（如果只有一个父级）这一个对象进行操作，这样我们就需要一个内存空间就够了，是不是省了很多，自然性能就会更好。</p>    <h3>事件委托的原理：</h3>   <p>事件委托是利用事件的冒泡原理来实现的，何为事件冒泡呢？就是事件从最深的节点开始，然后逐步向上传播事件，举个例子：页面上有这么一个节点树，div&gt;ul&gt;li&gt;a;比如给最里面的a加一个click点击事件，那么这个事件就会一层一层的往外执行，执行顺序a&gt;li&gt;ul&gt;div，有这样一个机制，那么我们给最外面的div加点击事件，那么里面的ul，li，a做点击事件的时候，都会冒泡到最外层的div上，所以都会触发，这就是事件委托，委托它们父级代为执行事件。</p>    <h3>事件委托怎么实现：</h3>   <p>终于到了本文的核心部分了，哈哈，在介绍事件委托的方法之前，我们先来看一段一般方法的例子：</p>    <p>子节点实现相同的功能：</p>    <div class="cnblogs_code">     <pre><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ul </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">=&quot;ul1&quot;</span><span style="color: #0000ff;">&gt;</span>    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>111<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>222<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>333<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>444<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">ul</span><span style="color: #0000ff;">&gt;</span></pre>    </div>    <p>实现功能是点击li，弹出123：</p>    <div class="cnblogs_code">         <pre>window.onload = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){    </span><span style="color: #0000ff;">var</span> oUl = document.getElementById(&quot;ul1&quot;<span style="color: #000000;">);    </span><span style="color: #0000ff;">var</span> aLi = oUl.getElementsByTagName('li'<span style="color: #000000;">);    </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">var</span> i=0;i&lt;aLi.length;i++<span style="color: #000000;">){        aLi[i].onclick </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){            alert(</span><span><span style="color: #0000ff;">123</span></span><span style="color: #000000;">);        }    }}</span></pre>        </div>    <p>&nbsp;上面的代码的意思很简单，相信很多人都是这么实现的，我们看看有多少次的dom操作，首先要找到ul，然后遍历li，然后点击li的时候，又要找一次目标的li的位置，才能执行最后的操作，每次点击都要找一次li；</p>    <p>那么我们用事件委托的方式做又会怎么样呢？</p>    <div class="cnblogs_code">     <pre>window.onload = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){    </span><span style="color: #0000ff;">var</span> oUl = document.getElementById(&quot;ul1&quot;<span style="color: #000000;">);   oUl.onclick </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){        alert(</span>123<span style="color: #000000;">);    }}</span></pre>    </div>    <p>&nbsp;</p>    <p>这里用父级ul做事件处理，当li被点击时，由于冒泡原理，事件就会冒泡到ul上，因为ul上有点击事件，所以事件就会触发，当然，这里当点击ul的时候，也是会触发的，那么问题就来了，如果我想让事件代理的效果跟直接给节点的事件效果一样怎么办，比如说只有点击li才会触发，不怕，我们有绝招：</p>    <p>Event对象提供了一个属性叫target，可以返回事件的目标节点，我们成为事件源，也就是说，target就可以表示为当前的事件操作的dom，但是不是真正操作dom，当然，这个是有兼容性的，标准浏览器用ev.target，IE浏览器用event.srcElement，此时只是获取了当前节点的位置，并不知道是什么节点名称，这里我们用nodeName来获取具体是什么标签名，这个返回的是一个大写的，我们需要转成小写再做比较（习惯问题）：</p>    <div class="cnblogs_code">        <div class="cnblogs_code"><p>window.onload = function(){<br>          　　var oUl = document.getElementById("ul1");<br>         　　oUl.onclick = function(ev){<br>               　　　　var ev = ev || window.event;<br>                　　　　var target = ev.target || ev.srcElement;<br>                　　　　if(target.nodeName.toLowerCase() == 'li'){<br>              　 　　　　　　    alert(123);<br>     　　　　　　　 &nbsp;alert(target.innerHTML);<br>              　　　　}<br>           　　}<br>     }</p><div class="cnblogs_code_toolbar"> </div>   </div>    <p>&nbsp;</p>    <p>这样改下就只有点击li会触发事件了，且每次只执行一次dom操作，如果li数量很多的话，将大大减少dom的操作，优化的性能可想而知！</p>    <p>&nbsp;</p>    <p>上面的例子是说li操作的是同样的效果，要是每个li被点击的效果都不一样，那么用事件委托还有用吗？</p>    <div class="cnblogs_code">     <pre><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">=&quot;box&quot;</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">input </span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">=&quot;button&quot;</span><span style="color: #ff0000;"> id</span><span style="color: #0000ff;">=&quot;add&quot;</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">=&quot;添加&quot;</span> <span style="color: #0000ff;">/&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">input </span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">=&quot;button&quot;</span><span style="color: #ff0000;"> id</span><span style="color: #0000ff;">=&quot;remove&quot;</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">=&quot;删除&quot;</span> <span style="color: #0000ff;">/&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">input </span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">=&quot;button&quot;</span><span style="color: #ff0000;"> id</span><span style="color: #0000ff;">=&quot;move&quot;</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">=&quot;移动&quot;</span> <span style="color: #0000ff;">/&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">input </span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">=&quot;button&quot;</span><span style="color: #ff0000;"> id</span><span style="color: #0000ff;">=&quot;select&quot;</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">=&quot;选择&quot;</span> <span style="color: #0000ff;">/&gt;</span>    <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span></pre>    </div>    <div class="cnblogs_code">         <pre>window.onload = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){            </span><span style="color: #0000ff;">var</span> Add = document.getElementById(&quot;add&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> Remove = document.getElementById(&quot;remove&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> Move = document.getElementById(&quot;move&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> Select = document.getElementById(&quot;select&quot;<span style="color: #000000;">);                        Add.onclick </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                alert(</span>'添加'<span style="color: #000000;">);            };            Remove.onclick </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                alert(</span>'删除'<span style="color: #000000;">);            };            Move.onclick </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                alert(</span>'移动'<span style="color: #000000;">);            };            Select.onclick </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                alert(</span>'选择'<span style="color: #000000;">);            }                    }</span></pre>        </div>    <p>&nbsp;</p>    <p>上面实现的效果我就不多说了，很简单，4个按钮，点击每一个做不同的操作，那么至少需要4次dom操作，如果用事件委托，能进行优化吗？</p>    <div class="cnblogs_code">         <pre>window.onload = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){            </span><span style="color: #0000ff;">var</span> oBox = document.getElementById(&quot;box&quot;<span style="color: #000000;">);            oBox.onclick </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;"> (ev) {                </span><span style="color: #0000ff;">var</span> ev = ev ||<span style="color: #000000;"> window.event;                </span><span style="color: #0000ff;">var</span> target = ev.target ||<span style="color: #000000;"> ev.srcElement;                </span><span style="color: #0000ff;">if</span>(target.nodeName.toLocaleLowerCase() == 'input'<span style="color: #000000;">){                    </span><span style="color: #0000ff;">switch</span><span style="color: #000000;">(target.id){                        </span><span style="color: #0000ff;">case</span> 'add'<span style="color: #000000;"> :                            alert(</span>'添加'<span style="color: #000000;">);                            </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;                        </span><span style="color: #0000ff;">case</span> 'remove'<span style="color: #000000;"> :                            alert(</span>'删除'<span style="color: #000000;">);                            </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;                        </span><span style="color: #0000ff;">case</span> 'move'<span style="color: #000000;"> :                            alert(</span>'移动'<span style="color: #000000;">);                            </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;                        </span><span style="color: #0000ff;">case</span> 'select'<span style="color: #000000;"> :                            alert(</span>'选择'<span style="color: #000000;">);                            </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;                    }                }            }                    }</span></pre>        </div>    <p>&nbsp;</p>    <p>用事件委托就可以只用一次dom操作就能完成所有的效果，比上面的性能肯定是要好一些的&nbsp;</p>    <p>&nbsp;</p>    <p>&nbsp;现在讲的都是document加载完成的现有dom节点下的操作，那么如果是新增的节点，新增的节点会有事件吗？也就是说，一个新员工来了，他能收到快递吗？</p>    <p>看一下正常的添加节点的方法：</p>    <div class="cnblogs_code">         <pre><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">input </span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">=&quot;button&quot;</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&quot;&quot;</span><span style="color: #ff0000;"> id</span><span style="color: #0000ff;">=&quot;btn&quot;</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">=&quot;添加&quot;</span> <span style="color: #0000ff;">/&gt;</span>    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ul </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">=&quot;ul1&quot;</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>111<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>222<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>333<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>444<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>    <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">ul</span><span style="color: #0000ff;">&gt;</span></pre>        </div>    <p>&nbsp;</p>    <p>现在是移入li，li变红，移出li，li变白，这么一个效果，然后点击按钮，可以向ul中添加一个li子节点</p>    <p>&nbsp;</p>    <div class="cnblogs_code">         <pre>window.onload = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){            </span><span style="color: #0000ff;">var</span> oBtn = document.getElementById(&quot;btn&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> oUl = document.getElementById(&quot;ul1&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> aLi = oUl.getElementsByTagName('li'<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> num = 4<span style="color: #000000;">;                        </span><span style="color: #008000;">//</span><span style="color: #008000;">鼠标移入变红，移出变白</span>            <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">var</span> i=0; i&lt;aLi.length;i++<span style="color: #000000;">){                aLi[i].onmouseover </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                    </span><span style="color: #0000ff;">this</span>.style.background = 'red'<span style="color: #000000;">;                };                aLi[i].onmouseout </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                    </span><span style="color: #0000ff;">this</span>.style.background = '#fff'<span style="color: #000000;">;                }            }            </span><span style="color: #008000;">//</span><span style="color: #008000;">添加新节点</span>            oBtn.onclick = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                num</span>++<span style="color: #000000;">;                </span><span style="color: #0000ff;">var</span> oLi = document.createElement('li'<span style="color: #000000;">);                oLi.innerHTML </span>= 111*<span style="color: #000000;">num;                oUl.appendChild(oLi);            };        }</span></pre>        </div>    <p>&nbsp;</p>    <p>这是一般的做法，但是你会发现，新增的li是没有事件的，说明添加子节点的时候，事件没有一起添加进去，这不是我们想要的结果，那怎么做呢？一般的解决方案会是这样，将for循环用一个函数包起来，命名为mHover，如下：</p>    <div class="cnblogs_code">         <pre>window.onload = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){            </span><span style="color: #0000ff;">var</span> oBtn = document.getElementById(&quot;btn&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> oUl = document.getElementById(&quot;ul1&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> aLi = oUl.getElementsByTagName('li'<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> num = 4<span style="color: #000000;">;                        </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> mHover () {                </span><span style="color: #008000;">//</span><span style="color: #008000;">鼠标移入变红，移出变白</span>                <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">var</span> i=0; i&lt;aLi.length;i++<span style="color: #000000;">){                    aLi[i].onmouseover </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                        </span><span style="color: #0000ff;">this</span>.style.background = 'red'<span style="color: #000000;">;                    };                    aLi[i].onmouseout </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                        </span><span style="color: #0000ff;">this</span>.style.background = '#fff'<span style="color: #000000;">;                    }                }            }            mHover ();            </span><span style="color: #008000;">//</span><span style="color: #008000;">添加新节点</span>            oBtn.onclick = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                num</span>++<span style="color: #000000;">;                </span><span style="color: #0000ff;">var</span> oLi = document.createElement('li'<span style="color: #000000;">);                oLi.innerHTML </span>= 111*<span style="color: #000000;">num;                oUl.appendChild(oLi);                mHover ();            };        }</span></pre>        </div>    <p>&nbsp;</p>    <p>虽然功能实现了，看着还挺好，但实际上无疑是又增加了一个dom操作，在优化性能方面是不可取的，那么有事件委托的方式，能做到优化吗？</p>    <div class="cnblogs_code">         <pre>window.onload = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){            </span><span style="color: #0000ff;">var</span> oBtn = document.getElementById(&quot;btn&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> oUl = document.getElementById(&quot;ul1&quot;<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> aLi = oUl.getElementsByTagName('li'<span style="color: #000000;">);            </span><span style="color: #0000ff;">var</span> num = 4<span style="color: #000000;">;                        </span><span style="color: #008000;">//</span><span style="color: #008000;">事件委托，添加的子元素也有事件</span>            oUl.onmouseover = <span style="color: #0000ff;">function</span><span style="color: #000000;">(ev){                </span><span style="color: #0000ff;">var</span> ev = ev ||<span style="color: #000000;"> window.event;                </span><span style="color: #0000ff;">var</span> target = ev.target ||<span style="color: #000000;"> ev.srcElement;                </span><span style="color: #0000ff;">if</span>(target.nodeName.toLowerCase() == 'li'<span style="color: #000000;">){                    target.style.background </span>= &quot;red&quot;<span style="color: #000000;">;                }                            };            oUl.onmouseout </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(ev){                </span><span style="color: #0000ff;">var</span> ev = ev ||<span style="color: #000000;"> window.event;                </span><span style="color: #0000ff;">var</span> target = ev.target ||<span style="color: #000000;"> ev.srcElement;                </span><span style="color: #0000ff;">if</span>(target.nodeName.toLowerCase() == 'li'<span style="color: #000000;">){                    target.style.background </span>= &quot;#fff&quot;<span style="color: #000000;">;                }                            };                        </span><span style="color: #008000;">//</span><span style="color: #008000;">添加新节点</span>            oBtn.onclick = <span style="color: #0000ff;">function</span><span style="color: #000000;">(){                num</span>++<span style="color: #000000;">;                </span><span style="color: #0000ff;">var</span> oLi = document.createElement('li'<span style="color: #000000;">);                oLi.innerHTML </span>= 111*<span style="color: #000000;">num;                oUl.appendChild(oLi);            };        }</span></pre>        </div>    <p>&nbsp;</p>    <p>看，上面是用事件委托的方式，新添加的子元素是带有事件效果的，我们可以发现，当用事件委托的时候，根本就不需要去遍历元素的子节点，只需要给父级元素添加事件就好了，其他的都是在js里面的执行，这样可以大大的减少dom操作，这才是事件委托的精髓所在。</p>    <p>&nbsp;</p> <hr>   <p>在这里先感谢一下@苍茫大地NV 的提问，提的问题非常好！&#55357;&#56399;&#55357;&#56399;&#55357;&#56399;</p>    <p>他的问题是：</p>    <p>现在给一个场景 ul &gt; li &gt; div &gt; p，div占满li，p占满div，还是给ul绑定时间，需要判断点击的是不是li（假设li里面的结构是不固定的），那么e.target就可能是p，也有可能是div，这种情况你会怎么处理呢？</p>    <p>那我们现在就再现一下他给的场景</p>    <div class="cnblogs_code">         <pre><span style="color: #0000ff;">　　&lt;</span><span style="color: #800000;">ul </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">=&quot;test&quot;</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span>11111111111<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">                22222222            </span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">span</span><span style="color: #0000ff;">&gt;</span>3333333333<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">span</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>4444444<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>    <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">ul</span><span style="color: #0000ff;">&gt;</span></pre>        </div>    <p>&nbsp;</p>    <p>&nbsp;</p>    <p>如上列表，有4个li，里面的内容各不相同，点击li，event对象肯定是当前点击的对象，怎么指定到li上，下面我直接给解决方案：</p>    <div class="cnblogs_code">         <pre><span style="color: #0000ff;">　　var</span> oUl = document.getElementById('test'<span style="color: #000000;">);    oUl.addEventListener(</span>'click',<span style="color: #0000ff;">function</span><span style="color: #000000;">(ev){        </span><span style="color: #0000ff;">var</span> target =<span style="color: #000000;"> ev.target;        </span><span style="color: #0000ff;">while</span>(target !==<span style="color: #000000;"> oUl ){            </span><span style="color: #0000ff;">if</span>(target.tagName.toLowerCase() == 'li'<span style="color: #000000;">){                console.log(</span>'li click~'<span style="color: #000000;">);                </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;            }            target </span>=<span style="color: #000000;"> target.parentNode;        }    })</span></pre>        </div>    <p>&nbsp;</p>    <p>&nbsp;核心代码是while循环部分，实际上就是一个递归调用，你也可以写成一个函数，用递归的方法来调用，同时用到冒泡的原理，从里往外冒泡，知道currentTarget为止，当当前的target是li的时候，就可以执行对应的事件了，然后终止循环，恩，没毛病！</p>    <p>这里看不到效果，大家可以复制过去运行一下！</p> <hr>   <h3>总结：</h3>   <p>那什么样的事件可以用事件委托，什么样的事件不可以用呢？</p>    <p>适合用事件委托的事件：click，mousedown，mouseup，keydown，keyup，keypress。</p>    <p>值得注意的是，mouseover和mouseout虽然也有事件冒泡，但是处理它们的时候需要特别的注意，因为需要经常计算它们的位置，处理起来不太容易。</p>    <p>不适合的就有很多了，举个例子，mousemove，每次都要计算它的位置，非常不好把控，在不如说focus，blur之类的，本身就没用冒泡的特性，自然就不能用事件委托了。</p>    <p>好了，今天就到这里，下次我想介绍一下事件绑定，欢迎大家关注和阅读，以上纯属个人见解，如有不对的地方，万望指正，不胜感谢！</p>    <p>&nbsp;</p>   </div> </body></html>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jQuery手动触发事件-trigger()方法</title>
      <link href="front/jquery/jq-trigger/"/>
      <url>front/jquery/jq-trigger/</url>
      
        <content type="html"><![CDATA[<div id="maincontent"><div class="backtoreference"><p><a href="/jquery/jquery_ref_events.asp" title="jQuery 参考手册 - 事件">jQuery 事件参考手册</a></p></div><div><h3>实例</h3><p>触发 input 元素的 select 事件：</p><pre>$("button").click(function(){  $("input").trigger("select");});</pre><p class="tiy"><a target="_blank" href="/tiy/t.asp?f=jquery_event_trigger">亲自试一试</a></p></div><div><h3>定义和用法</h3><p>trigger() 方法触发被选元素的指定事件类型。</p></div><div><h3>触发事件</h3><p>规定被选元素要触发的事件。</p><h3>语法</h3><pre>$(<i>selector</i>).trigger(<i>event</i>,[<i>param1</i>,<i>param2</i>,...])</pre><p class="tiy"><a target="_blank" href="/tiy/t.asp?f=jquery_event_trigger">亲自试一试</a></p><table class="dataintable"><tbody><tr><th style="width:25%;">参数</th><th>描述</th></tr><tr><td><i>event</i></td><td>    <p>必需。规定指定元素要触发的事件。</p>    <p>可以使自定义事件（使用 bind() 函数来附加），或者任何标准事件。</p></td></tr><tr><td>[<i>param1</i>,<i>param2</i>,...]</td><td>    <p>可选。传递到事件处理程序的额外参数。</p>    <p>额外的参数对自定义事件特别有用。</p></td></tr></tbody></table></div><div><h3>使用 Event 对象来触发事件</h3><p>规定使用事件对象的被选元素要触发的事件。</p><h3>语法</h3><pre>$(<i>selector</i>).trigger(<i>eventObj</i>)</pre><p class="tiy"><a target="_blank" href="/tiy/t.asp?f=jquery_event_trigger_object">亲自试一试</a></p><table class="dataintable"><tbody><tr><th style="width:25%;">参数</th><th>描述</th></tr><tr><td><i>eventObj</i></td><td>必需。规定事件发生时运行的函数。</td></tr></tbody></table></div><div class="backtoreference"><p><a href="/jquery/jquery_ref_events.asp" title="jQuery 参考手册 - 事件">jQuery 事件参考手册</a></p></div></div>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python实现自动推本地github博客到远程仓库</title>
      <link href="python/self_tool/python-auto-git-push-plus/"/>
      <url>python/self_tool/python-auto-git-push-plus/</url>
      
        <content type="html"><![CDATA[<h3 id="以前的简单版本"><a href="#以前的简单版本" class="headerlink" title="以前的简单版本"></a>以前的简单版本</h3><p>通过python中的os模块操作系统命令<br>详情可参考:<a href="https://victorfengming.gitee.io/python/self_tool/python-auto-git-push/">Python实现一行代码推本地git到远程仓库</a></p><h3 id="升级版本"><a href="#升级版本" class="headerlink" title="升级版本"></a>升级版本</h3><p>本次加入了监听文件修改功能<br>这样脚本只需在后台运行,即可检测到对应的文件夹中的内容是否变化</p><p>如果变化,则调用自动push函数,即可实现推本地仓库到远程中</p><h3 id="依赖库的配置"><a href="#依赖库的配置" class="headerlink" title="依赖库的配置"></a>依赖库的配置</h3><p>这里我们需要用到一个库watchdog</p><p>关于它的安装和使用可以参考:<a href="https://victorfengming.gitee.io/python/self_tool/python-listen-dir/">python中文件变化监控-watchdog</a></p><h3 id="代码如下"><a href="#代码如下" class="headerlink" title="代码如下:"></a>代码如下:</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="comment"># Created by victor</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本模块的功能:&lt;检测文件夹变化&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入watchdog对应模块</span></span><br><span class="line"><span class="keyword">from</span> watchdog.observers <span class="keyword">import</span> Observer</span><br><span class="line"><span class="keyword">from</span> watchdog.events <span class="keyword">import</span> *</span><br><span class="line"><span class="comment"># 导入时间模块</span></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="comment"># 导入系统模块</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">push</span>(<span class="params">change</span>):</span></span><br><span class="line">    print(<span class="string">&#x27;-&#x27;</span>*<span class="number">76</span>)</span><br><span class="line">    os.system(<span class="string">&#x27;git add .&#x27;</span>)</span><br><span class="line">    os.system(<span class="string">&#x27;git commit -m\&quot;auto&#x27;</span>+change+<span class="string">&#x27;\&quot;&#x27;</span>)</span><br><span class="line">    os.system(<span class="string">&#x27;git push -u origin master&#x27;</span>)</span><br><span class="line">    print(<span class="string">&#x27;-&#x27;</span>*<span class="number">76</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">FileEventHandler</span>(<span class="params">FileSystemEventHandler</span>):</span></span><br><span class="line">    <span class="comment"># 初始化魔术方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        FileSystemEventHandler.__init__(self)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 文件或文件夹移动</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_moved</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        <span class="keyword">if</span> event.is_directory:</span><br><span class="line">            print(<span class="string">&quot;directory moved from &#123;0&#125; to &#123;1&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path, event.dest_path))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;file moved from &#123;0&#125; to &#123;1&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path, event.dest_path))</span><br><span class="line">            <span class="comment"># 这里我们只判断文件修改,如需加入文件夹修改,只需在上面的if条件中调用push函数即可</span></span><br><span class="line">            push(<span class="string">&quot;文件移动: &#123;0&#125; to &#123;1&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path, event.dest_path))</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 创建文件或文件夹</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_created</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        <span class="keyword">if</span> event.is_directory:</span><br><span class="line">            print(<span class="string">&quot;directory created:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;file created:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">            push(<span class="string">&quot;创建文件:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 删除文件或文件夹</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_deleted</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        <span class="keyword">if</span> event.is_directory:</span><br><span class="line">            print(<span class="string">&quot;directory deleted:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;file deleted:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">            push(<span class="string">&quot;删除文件:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 移动文件或文件夹</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">on_modified</span>(<span class="params">self, event</span>):</span></span><br><span class="line">        <span class="keyword">if</span> event.is_directory:</span><br><span class="line">            print(<span class="string">&quot;directory modified:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">&quot;file modified:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line">            push(<span class="string">&quot;文件修改:&#123;0&#125;&quot;</span>.<span class="built_in">format</span>(event.src_path))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    <span class="comment"># 实例化Observer对象</span></span><br><span class="line">    observer = Observer()</span><br><span class="line">    event_handler = FileEventHandler()</span><br><span class="line">    <span class="comment"># 设置监听目录</span></span><br><span class="line">    dis_dir = <span class="string">&quot;./_posts/&quot;</span></span><br><span class="line">    observer.schedule(event_handler, dis_dir, <span class="literal">True</span>)</span><br><span class="line">    observer.start()</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">            <span class="comment"># 设置监听频率(间隔周期时间)</span></span><br><span class="line">            time.sleep(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">except</span> KeyboardInterrupt:</span><br><span class="line">        observer.stop()</span><br><span class="line">    observer.join()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> system </tag>
            
            <tag> Python </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python实现一行代码推本地git到远程仓库</title>
      <link href="python/self_tool/python-auto-git-push/"/>
      <url>python/self_tool/python-auto-git-push/</url>
      
        <content type="html"><![CDATA[<h3 id="普通的方式"><a href="#普通的方式" class="headerlink" title="普通的方式"></a>普通的方式</h3><p>刚刚学会git的你想要将你修改的code的文件push到远程仓库中的时候</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add .</span><br><span class="line">git commit -m&quot;本次修改就是啥也没动&quot;</span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure><h3 id="装13的方式"><a href="#装13的方式" class="headerlink" title="装13的方式"></a>装13的方式</h3><p>这三条命令应该是很多小伙伴们必须要输入的<br>小编这次就教大家用python写一个简单的脚本<br>实现,自动push你的git库中的code  </p><h3 id="具体实现"><a href="#具体实现" class="headerlink" title="具体实现"></a>具体实现</h3><p>首先我们需要一个操作系统的OS模块  </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="comment"># 调用os的system方法</span></span><br><span class="line">os.system(<span class="string">&#x27;git add .&#x27;</span>)</span><br><span class="line"><span class="comment"># 这里的参数就相当于在终端中输入的命令</span></span><br><span class="line">os.system(<span class="string">&#x27;git commit -m\&quot;python auto push\&quot;&#x27;</span>)</span><br><span class="line"><span class="comment"># 你可以自己定义自己的 commit 说明内容</span></span><br><span class="line">os.system(<span class="string">&#x27;git push origin master&#x27;</span>)</span><br><span class="line"><span class="comment"># 最后push到对应的远程库中的某个分之中,就成了</span></span><br></pre></td></tr></table></figure><p>编辑文件后,将文件保存为.py格式,例如<code>everydaypush.py</code><br>存到你的git库的根目录中<br>在终端中执行:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 everydaypush.py</span><br></pre></td></tr></table></figure><p>结果如下:<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/python/python-auto-git-push.png" alt="python auto git push"></p><p>小编后续会升级和完善相应功能,请持续关注~</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jQuery中的元素方法</title>
      <link href="front/jquery/jq-dom-method/"/>
      <url>front/jquery/jq-dom-method/</url>
      
        <content type="html"><![CDATA[<h3 id="先送你一个清单"><a href="#先送你一个清单" class="headerlink" title="先送你一个清单"></a>先送你一个清单</h3><table class="dataintable"><tbody><tr><th>函数</th><th>描述</th></tr><tr><td><a href="/jquery/dom_element_methods_get.asp" title="jQuery DOM 元素方法 - get() 方法">.get()</a></td><td>获得由选择器指定的 DOM 元素。</td></tr><tr><td><a href="/jquery/dom_element_methods_index.asp" title="jQuery DOM 元素方法 - index() 方法">.index()</a></td><td>返回指定元素相对于其他指定元素的 index 位置。</td></tr><tr><td><a href="/jquery/dom_element_methods_size.asp" title="jQuery DOM 元素方法 - size() 方法">.size()</a></td><td>返回被 jQuery 选择器匹配的元素的数量。</td></tr><tr><td><a href="/jquery/dom_element_methods_toarray.asp" title="jQuery DOM 元素方法 - toArray() 方法">.toArray()</a></td><td>以数组的形式返回 jQuery 选择器匹配的元素。</td></tr></tbody></table><h3 id="举个栗子"><a href="#举个栗子" class="headerlink" title="举个栗子"></a>举个栗子</h3><p>元素结构是这样的  </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;ul&gt;</span><br><span class="line">  &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">  &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">  &lt;li&gt;&lt;&#x2F;li&gt;</span><br><span class="line">&lt;&#x2F;ul&gt;</span><br></pre></td></tr></table></figure><p>如要获取上述html中li的数量:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$(&quot;ul &gt; li&quot;).length;</span><br></pre></td></tr></table></figure><p>或使用其size()方法:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$(&quot;ul &gt; li&quot;).size();</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jquery点击事件获取该元素在整个一类元素中的索引值</title>
      <link href="front/jquery/jq-event-get-index/"/>
      <url>front/jquery/jq-event-get-index/</url>
      
        <content type="html"><![CDATA[<div class="htmledit_views" id="content_views">                                            <pre style="font-family:'新宋体';font-size:13px;background:#FFFFFF;">有一类div标签，class为pointbox，数量不等，有多个。我需要在点击某一个标签的时候实时获取该标签在这类标签中索引值，以便进行其他操作。</pre><pre style="font-family:'新宋体';font-size:13px;background:#FFFFFF;">代码很简单：</pre><pre style="font-family:'新宋体';font-size:13px;background:#FFFFFF;">$(<span style="color:#a31515;">".pointbox"</span>).click(<span style="color:#0000FF;">function</span>&nbsp;()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;<span style="color:#0000FF;">var</span>&nbsp;index=$(<span style="color:#a31515;">".pointbox"</span>).index($(<span style="color:#0000FF;">this</span>));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</pre><pre style="font-family:'新宋体';font-size:13px;background:#FFFFFF;">但是比较实用,送你啦,拿去不谢!</pre></div>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>js和jq选择相关</title>
      <link href="front/js/js-select-get-index/"/>
      <url>front/js/js-select-get-index/</url>
      
        <content type="html"><![CDATA[<h3 id="原生js"><a href="#原生js" class="headerlink" title="原生js"></a>原生js</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">var   mySelect &#x3D; document.getElementById(”testSelect”);&#x2F;&#x2F;定位id(获取select)</span><br><span class="line">    </span><br><span class="line">var   index &#x3D;mySelect.selectedIndex;&#x2F;&#x2F; 选中索引(选取select中option选中的第几个)</span><br><span class="line">    </span><br><span class="line">var   text &#x3D;mySelect.options[index].text; &#x2F;&#x2F; 选中文本</span><br><span class="line">    </span><br><span class="line">var   value &#x3D;mySelect.options[index].value; &#x2F;&#x2F; 选中值</span><br><span class="line"> </span><br><span class="line">mySelect.options[index].selected &#x2F;&#x2F; 判断select中的某个option是否选中   true为选中   false 为未选中</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if(mySelect.options[1].selected &#x3D;&#x3D; true)&#123;</span><br><span class="line">   console.log(1)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="JQ部分"><a href="#JQ部分" class="headerlink" title="JQ部分"></a>JQ部分</h3><h3 id="1-判断option是否被选中"><a href="#1-判断option是否被选中" class="headerlink" title="1.判断option是否被选中"></a>1.判断option是否被选中</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$(&quot;#id&quot;).is(&quot;:checked&quot;)&#x2F;&#x2F;为false时是未被选中的，为true时是被选中</span><br><span class="line"></span><br><span class="line">$(&quot;#id&quot;).attr(&#39;checked&#39;)&#x3D;&#x3D;undefined&#x2F;&#x2F;为false时是未被选中的，为true时是被选中</span><br></pre></td></tr></table></figure><h3 id="2-获取select选中的值"><a href="#2-获取select选中的值" class="headerlink" title="2.获取select选中的值"></a>2.获取select选中的值</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$(&quot;#mySelect option:selected&quot;).text()</span><br><span class="line"></span><br><span class="line">$(&quot;#mySelect&quot;).find(&#39;option:selected&#39;).text()</span><br><span class="line"></span><br><span class="line">$(&quot;#mySelect&quot;).val();</span><br></pre></td></tr></table></figure><h3 id="3-获取select选中的索引"><a href="#3-获取select选中的索引" class="headerlink" title="3.获取select选中的索引"></a>3.获取select选中的索引</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$(&quot;#mySelect&quot;).get(0).selectedindex</span><br></pre></td></tr></table></figure><h3 id="4-添加option"><a href="#4-添加option" class="headerlink" title="4.添加option"></a>4.添加option</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$(&quot;#mySelect&quot;).append(&quot;&lt;option value&#x3D;&quot;+value+&quot;&gt;&quot;+text+&quot;&lt;option&gt;&quot;);</span><br></pre></td></tr></table></figure><h3 id="5-删除option"><a href="#5-删除option" class="headerlink" title="5.删除option"></a>5.删除option</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$(&quot;#myOption&quot;).remove()</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>git log解析</title>
      <link href="git/git-log-analysis/"/>
      <url>git/git-log-analysis/</url>
      
        <content type="html"><![CDATA[<div id="cnblogs_post_body" class="blogpost-body ">    <p><!--?xml version="1.0" encoding="UTF-8" standalone="no"?--></p><div>git log命令非常强大而好用，在复杂系统的版本管理中扮演着重要的角色，但默认的git log命令显示出的东西实在太丑，不好好打扮一下根本没法见人，打扮好了用alias命令拍个照片，就正式出道了！</div><div>&nbsp;</div><div>下面先详细而系统地介绍git log的所有配置知识（用我一向简洁清晰的表述方式），熟悉了这些东西，你就可以自由配置自己美丽的git log了～</div><div>最后上个干货，直接给一个我打扮好的alias配置，懒人直接跳到最后吧 ！</div><div>&nbsp;</div><div>（转载请注明：博客园-阁刚广志，地址：http://www.cnblogs.com/bellkosmos/p/5923439.html&nbsp;）</div><div>&nbsp;</div><div><!--?xml version="1.0" encoding="UTF-8" standalone="no"?--><div>git log用于查询版本的历史，命令形式如下：</div><div><div class="cnblogs_code"><pre>git log [&lt;options&gt;] [&lt;since&gt;..&lt;until&gt;] [[--] &lt;path&gt;...]</pre></div><p>&nbsp;</p></div><div>这条命令有很多参数选项</div><div>一、不带参数</div><ol><li>如果不带任何参数，它会列出所有历史记录，最近的排在最上方，显示提交对象的哈希值，作者、提交日期、和提交说明</li><li>如果记录过多，则按Page Up、Page Down、↓、↑来控制显示</li><li>按q退出历史记录列表</li></ol><div>&nbsp;</div><div>二、显示参数</div><ol><li>-p：按补丁显示每个更新间的差异，比下一条- -stat命令信息更全</li><li>--stat：显示每次更新的修改文件的统计信息，每个提交都列出了修改过的文件，以及其中添加和移除的行数，并在最后列出所有增减行数小计</li><li>--shortstat：只显示--stat中最后的行数添加修改删除统计</li><li>--name-only：尽在已修改的提交信息后显示文件清单</li><li>--name-status：显示新增、修改和删除的文件清单</li><li>--abbrev-commit：仅显示SHA-1的前几个字符，而非所有的40个字符</li><li>--relative-date：使用较短的相对时间显示（例如："two weeks ago"）</li><li>--graph：显示ASCII图形表示的分支合并历史</li><li>—pretty＝：使用其他格式显示历史提交信息，可选项有：oneline,short,medium,full,fuller,email,raw以及format:&lt;string&gt;,默认为medium，如：<ol><li><strong>--pretty=oneline：</strong>一行显示，只显示哈希值和提交说明（--online本身也可以作为单独的属性）</li><li><strong>--pretty=format:” "：</strong>控制显示的记录格式，如：<ol><li>%H&nbsp; 提交对象（commit）的完整哈希字串</li><li>%h&nbsp; 提交对象的简短哈希字串</li><li>%T&nbsp; 树对象（tree）的完整哈希字串</li><li>%t&nbsp; 树对象的简短哈希字串</li><li>%P&nbsp; 父对象（parent）的完整哈希字串</li><li>%p&nbsp; 父对象的简短哈希字串</li><li>%an 作者（author）的名字</li><li>%ae 作者的电子邮件地址</li><li>%ad 作者修订日期（可以用 -date= 选项定制格式）</li><li>%ar 作者修订日期，按多久以前的方式显示</li><li>%cn 提交者(committer)的名字<ol><li>作者和提交者的区别不知道是啥？</li><li>作者与提交者的关系：作者是程序的修改者，提交者是代码提交人（自己的修改不提交是怎么能让别人拉下来再提交的？）</li><li>其实作者指的是实际作出修改的人，提交者指的是最后将此工作成果提交到仓库的人。所以，当你为某个项目发布补丁，然后某个核心成员将你的补丁并入项目时，你就是作者，而那个核心成员就是提交者（soga）</li></ol></li><li>%ce 提交者的电子邮件地址</li><li>%cd 提交日期（可以用 -date= 选项定制格式）</li><li>%cr 提交日期，按多久以前的方式显示</li><li>%s&nbsp; 提交说明</li></ol></li><li>带颜色的<strong>--pretty=format:” "</strong>，这个另外写出来分析<ol><li>以这句为例：%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)&lt;%an&gt;</li><li>它的效果是：<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->&nbsp;<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->&nbsp;<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->&nbsp;<img src= "/img/loading.gif" data-lazy-src="https://images2015.cnblogs.com/blog/748759/201609/748759-20160930121017813-427458411.png" alt=""><p>&nbsp;</p></li><li>先断句：［%Cred%h］［%Creset &nbsp; -］［%C(yellow)%d ］［%Cblue%s］［%Cgreen(%cd)］［%C(bold blue)&lt;%an&gt;］</li><li>然后就是很明显能得到的规律了<ol><li>一个颜色＋一个内容</li><li>颜色以％C开头，后边接几种颜色，还可以设置字体，如果要设置字体的话，要一块加个括号<ol><li>能设置的颜色值包括：reset（默认的灰色），normal, black, red, green, yellow, blue, magenta, cyan, white.</li><li>字体属性则有bold, dim, ul, blink, reverse. &nbsp;</li></ol></li><li>内容可以是占位元字符，也可以是直接显示的普通字符</li></ol></li></ol></li></ol></li><li>--date= (relative|local|default|iso|rfc|short|raw)：定制后边如果出现%ad或%cd时的日期格式<ol><li>有几个默认选项<ol><li>--date=relative：shows dates relative to the current time, e.g. "2 hours ago".</li><li>--date=local：shows timestamps in user’s local timezone.</li><li>--date=iso (or --date=iso8601)：shows timestamps in ISO 8601 format.</li><li>--date=rfc (or --date=rfc2822)：shows timestamps in RFC 2822 format,often found in E-mail messages.</li><li>--date=short：shows only date but not time, in YYYY-MM-DD format.这个挺好用</li><li>--date=raw：shows the date in the internal raw git format %s %z format.</li><li>--date=default：shows timestamps in the original timezone&nbsp;(either committer’s or author’s).</li></ol></li><li>也可以自定义格式（需要git版本2.6.0以上），比如--date=format:'%Y-%m-%d %H:%M:%S' 会格式化成：2016-01-13 11:32:13，其他的格式化占位符如下：<ol><li>%a：Abbreviated weekday name</li><li>%A：Full weekday name</li><li>%b：Abbreviated month name</li><li>%B：Full month name</li><li>%c：Date and time representation appropriate for locale</li><li>%d：Day of month as decimal number (01 – 31)</li><li>%H： Hour in 24-hour format (00 – 23)</li><li>%I：Hour in 12-hour format (01 – 12)</li><li>%j：Day of year as decimal number (001 – 366)</li><li>%m：Month as decimal number (01 – 12)</li><li>%M：Minute as decimal number (00 – 59)</li><li>%p：Current locale's A.M./P.M. indicator for 12-hour clock</li><li>%S：Second as decimal number (00 – 59)</li><li>%U：Week of year as decimal number, with Sunday as first day of week (00 – 53)</li><li>%w：Weekday as decimal number (0 – 6; Sunday is 0)</li><li>%W：Week of year as decimal number, with Monday as first day of week (00 – 53)</li><li>%x：Date representation for current locale</li><li>%X：Time representation for current locale</li><li>%y：Year without century, as decimal number (00 – 99)</li><li>%Y：Year with century, as decimal number</li><li>%z, %Z：Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown</li><li>%%：Percent sign</li></ol></li></ol></li></ol><div>&nbsp;</div><div>三、筛选参数：</div><ol><li>按数量<ol><li>-n：显示前n条log</li></ol></li><li>按日期<ol><li>--after=<ol><li>比如git log --after="2014-7-1”，显示2014年7月1号之后的commit(包含7月1号)</li><li>后边的日期还可以用相对时间表示，比如"1 week ago"和”yesterday"，比如git log --after="yesterday"</li><li>这里的格式可以是什么？</li></ol></li><li>--before=<ol><li>同上</li><li>另外这两条命令可以同时使用表示时间段，比如git log --after="2014-7-1" --before="2014-7-4"</li><li>另外--since --until和 --after --before是一个意思，都可以用</li></ol></li></ol></li><li>按作者<ol><li>--author=<ol><li>比如git log --author=“John"，显示John贡献的commit</li><li>注意：作者名不需要精确匹配，只需要包含就行了</li><li>而且：可以使用正则表达式，比如git log --author="John\|Mary”，搜索Marry和John贡献的commit</li><li>而且：这个--author不仅包含名还包含email, 所以你可以用这个搜索email</li></ol></li></ol></li><li>按commit描述<ol><li>--grep=<ol><li>比如：git log --grep="JRA-224"</li><li>而且：可以传入-i用来忽略大小写</li><li>注意：如果想同时使用--grep和--author，必须在附加一个--all-match参数</li></ol></li></ol></li><li>按文件<ol><li>- -（空格）或［没有］<ol><li>有时你可能只对某个文件的修改感兴趣, 你只想查看跟某个文件相关的历史信息, 你只需要插入你感兴趣文件的路径［对，是路径，所以经常是不太好用］就可以了</li><li>比如：git log -- foo.py bar.py ，只返回和foo.py或bar.py相关的commit</li><li>这里的--是告诉Git后面的参数是文件路径而不是branch的名字. 如果后面的文件路径不会和某个branch产生混淆, 你可以省略- -，比如git log foo.py&nbsp;</li><li>另外，后边的路径还支持正则，比如：git log&nbsp; *install.md 是，指定项目路径下的所有以install.md结尾的文件的提交历史</li><li>另外，文件名应该放到参数的最后位置，通常在前面加上--并用空格隔开表示是文件</li><li>另外，git log file/ 查看file文件夹下所有文件的提交记录</li></ol></li></ol></li><li>按分支<ol><li>- -<ol><li>--branchName branchName为任意一个分支名字，查看某个分支上的提交记录</li><li>需要放到参数中的最后位置处</li><li>如果分支名与文件名相同，系统会提示错 误，可通过--选项来指定给定的参数是分支名还是文件名<ol><li>比如：在当前分支中有一个名为v1的文件，同时还存在一个名为v1的分支</li><li>git log v1 -- 此时的v1代表的是分支名字（－－后边是空的）</li><li>git log -- v1 此时的v1代表的是名为v1的文件</li><li>git log v1 －－ v1 代表v1分支下的v1文件</li></ol></li></ol></li></ol></li><li>按内容<ol><li>-S"&lt;string&gt;"、-G"&lt;string&gt;"<ol><li>有时你想搜索和新增或删除某行代码相关的commit. 可以使用这条命令</li><li>假设你想知道Hello, World!这句话是什么时候加入到项目里去的，可以用：git log -S"Hello,World!"</li><li>另外：如果你想使用正则表达式去匹配而不是字符串, 那么你可以使用-G代替-S.</li><li>这是一个非常有用的debug工具, 使用他你可以定位所有跟某行代码相关的commit. 甚至可以查看某行是什么时候被copy的, 什么时候移到另外一个文件中去的</li><li>注：-S后没有"="，与查询内容之间也没有空格符</li></ol></li></ol></li><li>按范围<ol><li>git log &lt;since&gt;..&lt;until&gt;<ol><li>这个命令可以查看某个范围的commit</li><li>这个命令非常有用当你使用branch做为range参数的时候. 能很方便的显示2个branch之间的不同</li><li>比如：git log master..feature，master..feature这个range包含了在feature有而在master没有的所有commit，同样，如果是feature..master包含所有master有但是feature没有的commit</li><li>另外，如果是三个点，表示或的意思：git log master...test 查询master或test分支中的提交记录</li></ol></li></ol></li><li>过滤掉merge commit<ol><li>--no-merges<ol><li>默认情况下git log会输出merge commit.&nbsp; 你可以通过--no-merges标记来过滤掉merge commit，git log --no-merges</li><li>另外，如果你只对merge commit感兴趣可以使用—merges，git log --merges</li></ol></li></ol></li><li>按标签tag<ol><li>git log v1.0<ol><li>直接这样是查询标签之前的commit</li><li>加两个点git log v1.0.. 查询从v1.0以后的提交历史记录(不包含v1.0)</li></ol></li></ol></li><li>按commit<ol><li>git log commit ：查询commit之前的记录，包含commit</li><li>git log commit1 commit2：查询commit1与commit2之间的记录，包括commit1和commit2</li><li>git log commit1..commit2：同上，但是不包括commit1<ol><li>其中，commit可以是提交哈希值的简写模式，也可以使用HEAD代替<ol><li>HEAD代表最后一次提交，HEAD^为最后一个提交的父提交，等同于HEAD～1</li><li>HEAD～2代表倒数第二次提交</li></ol></li></ol></li></ol></li></ol><div>&nbsp;</div></div><div>最后干货，你会喜欢的~</div><div>下面第一条的效果是这样：</div><div><img src= "/img/loading.gif" data-lazy-src="https://images2015.cnblogs.com/blog/748759/201702/748759-20170221115250304-122758740.png" alt=""><p>&nbsp;</p></div><div><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div><pre>git config --global alias.lm  "log --no-merges --color --date=format:'%Y-%m-%d %H:%M:%S' --author='你的名字！自己修改！' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)&lt;%an&gt;%Creset' --abbrev-commit"<br><br><span style="color: #000000;">git config </span>--global alias.lms  "log --no-merges --color --stat --date=format:'%Y-%m-%d %H:%M:%S' --author='你的名字！自己修改！' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)&lt;%an&gt;%Creset' --abbrev-commit"<br><br><span style="color: #000000;">git config </span>--global alias.ls "log --no-merges --color --graph --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)&lt;%an&gt;%Creset' --abbrev-commit"<br><br><span style="color: #000000;">git config </span>--global alias.lss "log --no-merges --color --stat --graph --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)&lt;%an&gt;%Creset' --abbrev-commit"</pre><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src= "/img/loading.gif" data-lazy-src="//common.cnblogs.com/img/copycode.gif" alt="复制代码"></a></span></div></div><p>&nbsp;</p></div><div>参考资料：</div><div><!--?xml version="1.0" encoding="UTF-8" standalone="no"?--><div><a href="http://www.cnblogs.com/irocker/p/advanced-git-log.html">http://www.cnblogs.com/irocker/p/advanced-git-log.html</a></div><div><a href="http://stackoverflow.com/questions/7853332/git-log-date-formats">http://stackoverflow.com/questions/7853332/git-log-date-formats</a></div><div><a href="https://git-scm.com/docs/git-log">https://git-scm.com/docs/git-log</a></div></div><div>&nbsp;</div><div>&nbsp;</div></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JS中的document.write和innerHTML区别</title>
      <link href="front/js/js-docwrite-innerhtml/"/>
      <url>front/js/js-docwrite-innerhtml/</url>
      
        <content type="html"><![CDATA[<p>链接：<a href="https://www.nowcoder.com/questionTerminal/2c5d8105b2694d85b06eff85e871cf50">https://www.nowcoder.com/questionTerminal/2c5d8105b2694d85b06eff85e871cf50</a></p><p>来源：牛客网 </p><h3 id="解释一"><a href="#解释一" class="headerlink" title="解释一"></a>解释一</h3><p>document.write是直接写入到页面的内容流，如果在写之前没有调用document.open, 浏览器会自动调用open。</p><p>每次写完关闭之后重新调用该函数，会导致页面被重写。</p><p>innerHTML则是DOM页面元素的一个属性，代表该元素的html内容。</p><p>你可以精确到某一个具体的元素来进行更改。</p><p>如果想修改document的内容，则需要修改document.documentElement.innerElement。</p><p>innerHTML很多情况下都优于document.write，其原因在于其允许更精确的控制要刷新页面的那一个部分。</p><h3 id="解释二"><a href="#解释二" class="headerlink" title="解释二"></a>解释二</h3><p>1.write是DOM方法,向文档写入HTML表达式或JavaScript代码，可列出多个参数，参数被顺序添加到文档中 ；innerHTML是DOM属性,设置或返回调用元素开始结束标签之间的HTML元素。</p><p>2.两者都可向页面输出内容,innerHTML比document.write更灵活。</p><p>当文档加载时调用document.write直接向页面输出内容，文档加载结束后调用document.write输出内容会重写整个页面。</p><p>通常按照两种的方式使用 write() 方法：一是在使用该方在文档中输出 HTML，二是在调用该方法的的窗口之外的窗口、框架中产生新文档（务必使用close关闭文档）。</p><p>在读模式下，innerHTML属性返回与调用元素的所有子节点对应的HTML标记，在写模式下，innerHTML会根据指定的值创建新的DOM树替换调用元素原先的所有子节点。</p><p>3.两者都可动态包含外部资源如JavaScript文件</p><p>通过document.write插入<script>元素会自动执行其中的脚本；</p><p>大多数浏览器中，通过innerHTML插入<script>元素并不会执行其中的脚本。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JS中的排他思想</title>
      <link href="front/js/js-out-others/"/>
      <url>front/js/js-out-others/</url>
      
        <content type="html"><![CDATA[<div class="content">本篇文章给大家分享了关于JS的排他思想的一点内容，有兴趣的朋友看一下<p></p><p>今天学习的JS中，要实现tba栏切换效果，运用了排他思想。</p><p><span class="img-wrap"><img src= "/img/loading.gif" data-lazy-src="https://img.php.cn/upload/article/000/153/291/edb090b1ed271d41d9711e85fc710063-0.png"></span></p><p>用户点击button时，不但button的背景颜色会改变，而且下面的内容也会随之改变。</p><p><span class="img-wrap"><img src= "/img/loading.gif" data-lazy-src="https://img.php.cn/upload/article/000/153/291/5c3ee46132e9f02d23ff1e8ad4ca4680-1.png"></span></p><p>首先要实现button的改变，用for循环遍历每个button，对所有的button进行初始化，使其类名为空；然后跳出循环，对当前被点击的button赋予一个类。</p><p><span class="img-wrap"><img src= "/img/loading.gif" data-lazy-src="https://img.php.cn/upload/article/000/153/291/5c3ee46132e9f02d23ff1e8ad4ca4680-2.png"></span></p><p>而对于下面每个盒子随着button的不同而改变，首先得先得到每个button的序号，对每个进行匹配，使之互相对应。</p><p><span class="img-wrap"><img src= "/img/loading.gif" data-lazy-src="https://img.php.cn/upload/article/000/153/291/df174f38274120d26cfbf0ccda10f945-3.png"></span></p><p>以上就是JS的排他思想的详细内容，更多请关注php中文网其它相关文章！</p><div class="share layui-clear bdsharebuttonbox bdshare-button-style0-16" data-bd-bind="1567767708992"><li><a href="javascript:;" data-cmd="weixin" class="wechat"><i class="layui-icon"></i>微信</a></li><li><a href="javascript:;" data-cmd="more" class="share-btn"><i class="layui-icon"></i>分享</a></li></div><img src= "/img/loading.gif" data-lazy-src="/static/img/article_wechat.jpg?1" style="margin-top: 30px;" alt="php中文网最新课程二维码"><div class="tags layui-clear"><li>相关标签：<a href="/search?word=javascript" target="_blank">javascript</a> <a href="/search?word=思想" target="_blank">思想</a> <a href="/search?word=排他" target="_blank">排他</a></li><li class="line">本文原创发布php中文网，转载请注明出处，感谢您的尊重！</li></div><div class="page layui-clear"><ul><li>上一篇：<a href="/js-tutorial-390900.html">ajax和jsonp跨域详解（附代码）</a></li><li>下一篇：<a href="/js-tutorial-390902.html">怎样用Ajax异步检查用户名有无重复</a></li></ul></div></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Git常用命令清单(全)</title>
      <link href="git/git-list/"/>
      <url>git/git-list/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「ouyangshima」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。<br>原文链接：<a href="https://blog.csdn.net/shimazhuge/article/details/52759429">https://blog.csdn.net/shimazhuge/article/details/52759429</a></p><div class="htmledit_views" id="content_views">                                            <p><a href="http://www.ruanyifeng.com/blog/2014/06/git_remote.html" rel="nofollow" data-token="7d06ac4b9bd7253bcdfb371b95ba0da1">Git远程操作--remote,fetch,clone,push,pull</a></p><p>一般来说，日常使用只要记住下图6个命令，就可以了。但是熟练使用，恐怕要记住60～100个命令。</p><p>&nbsp;</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20161008181448461"><br>下面是我整理的常用 Git 命令清单。几个专用名词的译名如下。</p><p>&nbsp;</p><ul><li>&nbsp;Workspace：工作区</li>    <li>&nbsp;Index / Stage：暂存区</li>    <li>&nbsp;Repository：仓库区（或本地仓库）</li>    <li>&nbsp;Remote：远程仓库</li></ul><p>&nbsp;</p><p><a href="https://try.github.io/levels/1/challenges/1" rel="nofollow" data-token="8ab91b8db4cc8c0eda9da872d048ae0c">在线git命令</a></p><p>&nbsp;</p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20180907153205990?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L291eWFuZ3NoaW1h/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"></p><p>&nbsp;</p><h3><a name="t0"></a>一、新建代码库</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 在当前目录新建一个Git代码库</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git init</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个目录，将其初始化为Git代码库</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git init [project-name]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 下载一个项目和它的整个代码历史</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git clone [url]</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t1"></a>二、配置</h3><p>&nbsp;</p><p>Git的设置文件为.gitconfig，它可以在用户主目录下（全局配置），也可以在项目目录下（项目配置）。</p><p>&nbsp;</p><pre class="has" name="code"><code class="hljs php"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示当前的Git配置</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git config --<span class="hljs-keyword">list</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 编辑Git配置文件</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git config -e [--<span class="hljs-keyword">global</span>]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 设置提交代码时的用户信息</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git config [--<span class="hljs-keyword">global</span>] user.name <span class="hljs-string">"[name]"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git config [--<span class="hljs-keyword">global</span>] user.email <span class="hljs-string">"[email address]"</span></div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t2"></a>三、增加/删除文件</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 添加指定文件到暂存区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git add [file1] [file2] ...</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 添加指定目录到暂存区，包括子目录</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git add [dir]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 添加当前目录的所有文件到暂存区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git add .</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 添加每个变化前，都会要求确认</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 对于同一个文件的多处变化，可以实现分次提交</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git add -p</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 删除工作区文件，并且将这次删除放入暂存区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git rm [file1] [file2] ...</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 停止追踪指定文件，但该文件会保留在工作区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git rm --cached [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 改名文件，并且将这个改名放入暂存区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git mv [file-original] [file-renamed]</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t3"></a>四、代码提交</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 提交暂存区到仓库区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git commit -m [message]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 提交暂存区的指定文件到仓库区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git commit [file1] [file2] ... -m [message]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 提交工作区自上次commit之后的变化，直接到仓库区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git commit -a</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 提交时显示所有diff信息</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git commit -v</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 使用一次新的commit，替代上一次提交</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 如果代码没有任何新变化，则用来改写上一次commit的提交信息</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git commit --amend -m [message]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 重做上一次commit，并包括指定文件的新变化</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git commit --amend [file1] [file2] ...</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t4"></a>五、分支</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 列出所有本地分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 列出所有远程分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch -r</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 列出所有本地分支和远程分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch -a</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个分支，但依然停留在当前分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch [branch-name]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个分支，并切换到该分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git checkout -b [branch]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个分支，指向指定commit</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch [branch] [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个分支，与指定的远程分支建立追踪关系</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch --track [branch] [remote-branch]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 切换到指定分支，并更新工作区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git checkout [branch-name]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="24"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="25"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 切换到上一个分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="26"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git checkout -</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="27"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="28"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 建立追踪关系，在现有分支与指定的远程分支之间</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="29"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch --set-upstream [branch] [remote-branch]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="30"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="31"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 合并指定分支到当前分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="32"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git merge [branch]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="33"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="34"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 选择一个commit，合并进当前分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="35"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git cherry-pick [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="36"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="37"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 删除分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="38"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch -d [branch-name]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="39"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="40"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 删除远程分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="41"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git push origin --delete [branch-name]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="42"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git branch -dr [remote/branch]</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t5"></a>六、标签</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 列出所有tag</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git tag</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个tag在当前commit</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git tag [tag]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个tag在指定commit</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git tag [tag] [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 删除本地tag</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git tag -d [tag]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 删除远程tag</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git push origin <span class="hljs-symbol">:refs/tags/</span>[tagName]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 查看tag信息</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git show [tag]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 提交指定tag</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git push [remote] [tag]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 提交所有tag</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git push [remote] --tags</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="24"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="25"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个分支，指向某个tag</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="26"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git checkout -b [branch] [tag]</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t6"></a>七、查看信息</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示有变更的文件</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git status</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示当前分支的版本历史</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git log</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示commit历史，以及每次commit发生变更的文件</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git log --stat</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 搜索提交历史，根据关键词</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git log -S [keyword]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示某个commit之后的所有变动，每个commit占据一行</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git log [tag] HEAD --pretty=<span class="hljs-symbol">format:</span>%s</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示某个commit之后的所有变动，其"提交说明"必须符合搜索条件</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git log [tag] HEAD --grep feature</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示某个文件的版本历史，包括文件改名</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git log --follow [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git whatchanged [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示指定文件相关的每一次diff</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="24"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git log -p [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="25"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="26"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示过去5次提交</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="27"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git log -<span class="hljs-number">5</span> --pretty --oneline</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="28"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="29"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示所有提交过的用户，按提交次数排序</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="30"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git shortlog -sn</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="31"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="32"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示指定文件是什么人在什么时间修改过</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="33"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git blame [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="34"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="35"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示暂存区和工作区的差异</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="36"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git diff</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="37"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="38"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示暂存区和上一个commit的差异</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="39"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git diff --cached [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="40"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="41"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示工作区与当前分支最新commit之间的差异</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="42"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git diff HEAD</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="43"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="44"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示两次提交之间的差异</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="45"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git diff [first-branch]...[second-branch]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="46"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="47"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示今天你写了多少行代码</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="48"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git diff --shortstat <span class="hljs-string">"@&#123;0 day ago&#125;"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="49"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="50"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示某次提交的元数据和内容变化</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="51"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git show [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="52"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="53"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示某次提交发生变化的文件</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="54"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git show --name-only [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="55"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="56"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示某次提交时，某个文件的内容</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="57"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git show [commit]<span class="hljs-symbol">:</span>[filename]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="58"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="59"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示当前分支的最近几次提交</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="60"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git reflog</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t7"></a>八、远程同步</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 下载远程仓库的所有变动</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git fetch [remote]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示所有远程仓库</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git remote -v</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 显示某个远程仓库的信息</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git remote show [remote]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 增加一个新的远程仓库，并命名</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git remote add [shortname] [url]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 取回远程仓库的变化，并与本地分支合并</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git pull [remote] [branch]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 上传本地指定分支到远程仓库</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git push [remote] [branch]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 强行推送当前分支到远程仓库，即使有冲突</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git push [remote] --force</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 推送所有分支到远程仓库</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git push [remote] --all</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t8"></a>九、撤销</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 恢复暂存区的指定文件到工作区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git checkout [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 恢复某个commit的指定文件到暂存区和工作区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git checkout [commit] [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 恢复暂存区的所有文件到工作区</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git checkout .</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 重置暂存区的指定文件，与上一次commit保持一致，但工作区不变</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git reset [file]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 重置暂存区与工作区，与上一次commit保持一致</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git reset --hard</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 重置当前分支的指针为指定commit，同时重置暂存区，但工作区不变</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git reset [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 重置当前分支的HEAD为指定commit，同时重置暂存区和工作区，与指定commit一致</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git reset --hard [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 重置当前HEAD为指定commit，但保持暂存区和工作区不变</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git reset --keep [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="24"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="25"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 新建一个commit，用来撤销指定commit</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="26"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 后者的所有变化都将被前者抵消，并且应用到当前分支</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="27"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git revert [commit]</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="28"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="29"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 暂时将未提交的变化移除，稍后再移入</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="30"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git stash</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="31"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git stash pop</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><h3><a name="t9"></a>十、其他</h3><pre class="has" name="code"><code class="hljs ruby"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    <span class="hljs-comment"># 生成一个可供发布的压缩包</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">    $ git archive</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" onclick="hljs.copyCode(event)"></div></pre><p><a href="http://git.oschina.net/progit/" rel="nofollow" data-token="5c77c92338182df03cdb7f85625e5053"><strong>Pro Git（中文版）</strong></a></p><p><a href="http://marklodato.github.io/visual-git-guide/index-zh-cn.html" rel="nofollow" data-token="fea542acd3cdad0e07a12aede0bc38de">图解Git</a></p><p><img alt="" class="has" src= "/img/loading.gif" data-lazy-src="https://img-blog.csdn.net/20161008181839165"></p><p>&nbsp;</p><p>&nbsp;</p>                                    </div>]]></content>
      
      
      
        <tags>
            
            <tag> Git </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>CSS中的定位</title>
      <link href="front/css/css-positioning/"/>
      <url>front/css/css-positioning/</url>
      
        <content type="html"><![CDATA[<p><a href="https://www.w3school.com.cn/css/css_positioning.asp">点击这里跳转W3c原文链接</a>  </p><div id="maincontent"><h1>CSS 定位 (Positioning)</h1><div id="tpn"><ul class="prenext"><li class="pre"><a href="/css/css_margin_collapsing.asp" title="CSS 外边距合并">CSS 外边距合并</a></li><li class="next"><a href="/css/css_positioning_relative.asp" title="CSS 相对定位">CSS 相对定位</a></li></ul></div><div id="intro"><p><strong>CSS 定位 (Positioning) 属性允许你对元素进行定位。</strong></p></div><div><h2>CSS 定位和浮动</h2><p>CSS 为定位和浮动提供了一些属性，利用这些属性，可以建立列式布局，将布局的一部分与另一部分重叠，还可以完成多年来通常需要使用多个表格才能完成的任务。</p><p>定位的基本思想很简单，它允许你定义元素框相对于其正常位置应该出现的位置，或者相对于父元素、另一个元素甚至浏览器窗口本身的位置。显然，这个功能非常强大，也很让人吃惊。要知道，用户代理对 CSS2 中定位的支持远胜于对其它方面的支持，对此不应感到奇怪。</p><p>另一方面，CSS1 中首次提出了浮动，它以 Netscape 在 Web 发展初期增加的一个功能为基础。浮动不完全是定位，不过，它当然也不是正常流布局。我们会在后面的章节中明确浮动的含义。</p></div><div><h2>一切皆为框</h2><p>div、h1 或 p 元素常常被称为块级元素。这意味着这些元素显示为<em>一块内容</em>，即“块框”。与之相反，span 和 strong 等元素称为“行内元素”，这是因为它们的内容显示在行中，即“行内框”。</p><p>您可以使用 <a href="/cssref/pr_class_display.asp" title="CSS display 属性">display 属性</a>改变生成的框的类型。这意味着，通过将 display 属性设置为 block，可以让行内元素（比如 &lt;a&gt; 元素）表现得像块级元素一样。还可以通过把 display 设置为 none，让生成的元素根本没有框。这样的话，该框及其所有内容就不再显示，不占用文档中的空间。</p><p>但是在一种情况下，即使没有进行显式定义，也会创建块级元素。这种情况发生在把一些文本添加到一个块级元素（比如 div）的开头。即使没有把这些文本定义为段落，它也会被当作段落对待：</p><pre>&lt;div&gt;some text&lt;p&gt;Some more text.&lt;/p&gt;&lt;/div&gt;</pre><p>在这种情况下，这个框称为无名块框，因为它不与专门定义的元素相关联。</p><p>块级元素的文本行也会发生类似的情况。假设有一个包含三行文本的段落。每行文本形成一个无名框。无法直接对无名块或行框应用样式，因为没有可以应用样式的地方（注意，行框和行内框是两个概念）。但是，这有助于理解在屏幕上看到的所有东西都形成某种框。</p></div><div><h2>CSS 定位机制</h2><p>CSS 有三种基本的定位机制：普通流、浮动和绝对定位。</p><p>除非专门指定，否则所有框都在普通流中定位。也就是说，普通流中的元素的位置由元素在 (X)HTML 中的位置决定。</p><p>块级框从上到下一个接一个地排列，框之间的垂直距离是由框的垂直外边距计算出来。</p><p>行内框在一行中水平布置。可以使用水平内边距、边框和外边距调整它们的间距。但是，垂直内边距、边框和外边距不影响行内框的高度。由一行形成的水平框称为<em>行框（Line Box）</em>，行框的高度总是足以容纳它包含的所有行内框。不过，设置行高可以增加这个框的高度。</p><p>在下面的章节，我们会为您详细讲解相对定位、绝对定位和浮动。</p></div><div><h2>CSS position 属性</h2><p>通过使用 <a href="/cssref/pr_class_position.asp" title="CSS position 属性">position 属性</a>，我们可以选择 4 种不同类型的定位，这会影响元素框生成的方式。</p><p>position 属性值的含义：</p><dl class="define"><dt>static</dt><dd>元素框正常生成。块级元素生成一个矩形框，作为文档流的一部分，行内元素则会创建一个或多个行框，置于其父元素中。</dd><dt>relative</dt><dd>元素框偏移某个距离。元素仍保持其未定位前的形状，它原本所占的空间仍保留。</dd><dt>absolute</dt><dd>元素框从文档流完全删除，并相对于其包含块定位。包含块可能是文档中的另一个元素或者是初始包含块。元素原先在正常文档流中所占的空间会关闭，就好像元素原来不存在一样。元素定位后生成一个块级框，而不论原来它在正常流中生成何种类型的框。</dd><dt>fixed</dt><dd>元素框的表现类似于将 position 设置为 absolute，不过其包含块是视窗本身。</dd></dl><p class="tip"><span>提示：</span>相对定位实际上被看作普通流定位模型的一部分，因为元素的位置相对于它在普通流中的位置。</p></div><div class="example"><h2>实例</h2><dl><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_relative">定位：相对定位</a></dt><dd>本例演示如何相对于一个元素的正常位置来对其定位。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_absolute">定位：绝对定位</a></dt><dd>本例演示如何使用绝对值来对元素进行定位。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_fixed">定位：固定定位</a></dt><dd>本例演示如何相对于浏览器窗口来对元素进行定位。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_top">使用固定值设置图像的上边缘</a></dt><dd>本例演示如何使用固定值设置图像的上边缘。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_top_percent">使用百分比设置图像的上边缘</a></dt><dd>本例演示如何使用百分比值设置图像的上边缘。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_bottom">使用像素值设置图像的底部边缘</a></dt><dd>本例演示如何使用像素值设置图像的底部边缘。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_bottom_percent">使用百分比设置图像的底部边缘</a></dt><dd>本例演示如何使用百分比值设置图像的底部边缘。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_left">使用固定值设置图像的左边缘</a></dt><dd>本例演示如何使用固定值设置图像的左边缘。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_left_percent">使用百分比设置图像的左边缘</a></dt><dd>本例演示如何使用百分比值设置图像的左边缘。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_right">使用固定值设置图像的右边缘</a></dt><dd>本例演示如何使用固定值设置图像的右边缘。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_position_right_percent">使用百分比设置图像的右边缘</a></dt><dd>本例演示如何使用百分比值设置图像的右边缘。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_overflow">如何使用滚动条来显示元素内溢出的内容</a></dt><dd>本例演示当元素内容太大而超出规定区域时，如何设置溢出属性来规定相应的动作。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_pos_overflow_hidden">如何隐藏溢出元素中溢出的内容</a></dt><dd>本例演示在元素中的内容太大以至于无法适应指定的区域时，如何设置 overflow 属性来隐藏其内容。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_pos_overflow_auto">如何设置浏览器来自动地处理溢出</a></dt><dd>本例演示如何设置浏览器来自动地处理溢出。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_clip">设置元素的形状</a></dt><dd>本例演示如何设置元素的形状。此元素被剪裁到这个形状内，并显示出来。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_vertical-align">垂直排列图象</a></dt><dd>本例演示如何在文本中垂直排列图象。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_zindex2">Z-index</a></dt><dd>Z-index可被用于将在一个元素放置于另一元素之后。</dd><dt><a target="_blank" href="/tiy/t.asp?f=csse_zindex1">Z-index</a></dt><dd>上面的例子中的元素已经更改了Z-index。</dd></dl></div><div><h2>CSS 定位属性</h2><p>CSS 定位属性允许你对元素进行定位。</p><table class="dataintable">  <tbody><tr>    <th>属性</th>    <th>描述</th>  </tr>  <tr>    <td><a href="/cssref/pr_class_position.asp">position</a></td>    <td>把元素放置到一个静态的、相对的、绝对的、或固定的位置中。</td>  </tr>  <tr>    <td><a href="/cssref/pr_pos_top.asp">top</a></td>    <td>定义了一个定位元素的上外边距边界与其包含块上边界之间的偏移。</td>  </tr>  <tr>    <td><a href="/cssref/pr_pos_right.asp">right</a></td>    <td>定义了定位元素右外边距边界与其包含块右边界之间的偏移。</td>  </tr>  <tr>    <td><a href="/cssref/pr_pos_bottom.asp">bottom</a></td>    <td>定义了定位元素下外边距边界与其包含块下边界之间的偏移。</td>  </tr>  <tr>    <td><a href="/cssref/pr_pos_left.asp">left</a></td>    <td>定义了定位元素左外边距边界与其包含块左边界之间的偏移。</td>  </tr>  <tr>    <td><a href="/cssref/pr_pos_overflow.asp">overflow</a></td>    <td>设置当元素的内容溢出其区域时发生的事情。</td>  </tr>  <tr>    <td><a href="/cssref/pr_pos_clip.asp">clip</a></td>    <td>设置元素的形状。元素被剪入这个形状之中，然后显示出来。</td>  </tr>  <tr>    <td><a href="/cssref/pr_pos_vertical-align.asp">vertical-align</a></td>    <td>设置元素的垂直对齐方式。</td>  </tr>  <tr>    <td><a href="/cssref/pr_pos_z-index.asp">z-index</a></td>    <td>设置元素的堆叠顺序。</td>  </tr></tbody></table></div><div id="bpn"><ul class="prenext"><li class="pre"><a href="/css/css_margin_collapsing.asp" title="CSS 外边距合并">CSS 外边距合并</a></li><li class="next"><a href="/css/css_positioning_relative.asp" title="CSS 相对定位">CSS 相对定位</a></li></ul></div><div id="ad_footer"><a id="ad_footer_link" href="https://gio.ren/w/JoODXE9Y" title="VUE 进阶教程" target="_blank">VUE 进阶教程</a></div></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> css </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jQ实现放大镜特效</title>
      <link href="front/jquery/magnifing-glass/"/>
      <url>front/jquery/magnifing-glass/</url>
      
        <content type="html"><![CDATA[<p>下面代码是<a href="https://hejie615.github.io/">何杰</a>同学写的  </p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span>    </span><br><span class="line"><span class="css">    *&#123;<span class="attribute">margin</span>:<span class="number">0px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">padding</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line">    .img&#123;</span><br><span class="line"><span class="css">        <span class="attribute">width</span>: <span class="number">350px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">height</span>: <span class="number">350px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#ccc</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">margin</span>: <span class="number">100px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">position</span>: relative;</span></span><br><span class="line"><span class="css">        <span class="attribute">cursor</span>:move;</span></span><br><span class="line">    &#125;    </span><br><span class="line">    .bimg&#123;</span><br><span class="line"><span class="css">        <span class="attribute">position</span>: relative;</span></span><br><span class="line"><span class="css">        <span class="attribute">top</span>: -<span class="number">400px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">left</span>: <span class="number">500px</span>;         </span></span><br><span class="line"><span class="css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#ccc</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">width</span>: <span class="number">400px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">height</span>: <span class="number">400px</span>;         </span></span><br><span class="line"><span class="css">        <span class="attribute">overflow</span>: hidden;</span></span><br><span class="line"><span class="css">        <span class="attribute">display</span>: none;</span></span><br><span class="line">    &#125;  </span><br><span class="line">    #move&#123;</span><br><span class="line"><span class="css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="css">        <span class="attribute">width</span>: <span class="number">100px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">height</span>: <span class="number">100px</span>;        </span></span><br><span class="line"><span class="css">        <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(<span class="number">8</span>,<span class="number">152</span>,<span class="number">202</span>,<span class="number">0.2</span>);</span></span><br><span class="line"><span class="css">        <span class="attribute">top</span>: <span class="number">0px</span>;        </span></span><br><span class="line"><span class="css">        <span class="attribute">left</span>: <span class="number">0px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">display</span>: none;</span></span><br><span class="line">      &#125;   </span><br><span class="line">    .simg&#123;</span><br><span class="line"><span class="css">        <span class="attribute">width</span>: <span class="number">350px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">height</span>: <span class="number">350px</span>;</span></span><br><span class="line">    &#125;</span><br><span class="line"><span class="css">    <span class="selector-class">.bimg</span>&gt;<span class="selector-tag">img</span>&#123;</span></span><br><span class="line"><span class="css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="css">        <span class="attribute">left</span>: <span class="number">0px</span>;</span></span><br><span class="line"><span class="css">        <span class="attribute">top</span>: <span class="number">0px</span>;</span></span><br><span class="line">       &#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;img&quot;</span>&gt;</span>   </span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;simg&quot;</span>&gt;</span><span class="comment">&lt;!--小图片--&gt;</span>     </span><br><span class="line">            <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;2.jpg&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:350px;height: 350px;&quot;</span> /&gt;</span>     </span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;move&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="comment">&lt;!--放大区域--&gt;</span>  </span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>  </span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;bimg&quot;</span>&gt;</span><span class="comment">&lt;!--大图片--&gt;</span>    </span><br><span class="line">            <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;2.jpg&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:1400px;height: 1400px;&quot;</span> /&gt;</span>  </span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    </span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    $(<span class="built_in">document</span>).ready(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span></span><br><span class="line"></span><br><span class="line"><span class="javascript">        <span class="comment">//鼠标移动到图片显示，移除隐藏     </span></span></span><br><span class="line"><span class="javascript">        $(<span class="string">&quot;.img&quot;</span>).hover(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;           </span></span><br><span class="line"><span class="javascript">            $(<span class="string">&quot;.bimg&quot;</span>).css(<span class="string">&quot;display&quot;</span>,<span class="string">&quot;block&quot;</span>);          </span></span><br><span class="line"><span class="javascript">            $(<span class="string">&quot;#move&quot;</span>).css(<span class="string">&quot;display&quot;</span>,<span class="string">&quot;block&quot;</span>);       </span></span><br><span class="line"><span class="javascript">        &#125;,<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;       </span></span><br><span class="line"><span class="javascript">            $(<span class="string">&quot;.bimg&quot;</span>).css(<span class="string">&quot;display&quot;</span>,<span class="string">&quot;none&quot;</span>);         </span></span><br><span class="line"><span class="javascript">            $(<span class="string">&quot;#move&quot;</span>).css(<span class="string">&quot;display&quot;</span>,<span class="string">&quot;none&quot;</span>);       </span></span><br><span class="line">        &#125;);</span><br><span class="line"><span class="javascript">        <span class="comment">//放大区域移动，大图片移动</span></span></span><br><span class="line"><span class="javascript">        $(<span class="string">&quot;.img&quot;</span>).mousemove(<span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span></span><br><span class="line"><span class="javascript">            <span class="keyword">var</span> x = event.pageX;          </span></span><br><span class="line"><span class="javascript">            <span class="keyword">var</span> y = event.pageY;                   </span></span><br><span class="line"><span class="javascript">            <span class="keyword">var</span> nx = x - $(<span class="string">&quot;.img&quot;</span>).offset().left-$(<span class="string">&quot;#move&quot;</span>).width()/<span class="number">2</span>;            </span></span><br><span class="line"><span class="javascript">            <span class="keyword">var</span> ny = y - $(<span class="string">&quot;.img&quot;</span>).offset().top-$(<span class="string">&quot;#move&quot;</span>).height()/<span class="number">2</span>;           </span></span><br><span class="line">            if(nx &lt; 0)&#123; </span><br><span class="line">                nx = 0;</span><br><span class="line">            &#125;            </span><br><span class="line"><span class="javascript">            <span class="keyword">if</span>(nx &gt; $(<span class="string">&quot;.img&quot;</span>).width()-$(<span class="string">&quot;#move&quot;</span>).width())&#123;        </span></span><br><span class="line"><span class="javascript">                nx = $(<span class="string">&quot;.img&quot;</span>).width()-$(<span class="string">&quot;#move&quot;</span>).width();         </span></span><br><span class="line">            &#125;            </span><br><span class="line">            if(ny &lt; 0)&#123;       </span><br><span class="line">                ny = 0;            </span><br><span class="line">            &#125;            </span><br><span class="line"><span class="javascript">            <span class="keyword">if</span>(ny &gt; $(<span class="string">&quot;.img&quot;</span>).height()-$(<span class="string">&quot;#move&quot;</span>).height())&#123;       </span></span><br><span class="line"><span class="javascript">                ny = $(<span class="string">&quot;.img&quot;</span>).height()-$(<span class="string">&quot;#move&quot;</span>).height();     </span></span><br><span class="line">            &#125;                </span><br><span class="line"><span class="javascript">            $(<span class="string">&quot;#move&quot;</span>).css(&#123;           </span></span><br><span class="line"><span class="javascript">                left:nx+<span class="string">&quot;px&quot;</span>,           </span></span><br><span class="line"><span class="javascript">                top:ny+<span class="string">&quot;px&quot;</span>       </span></span><br><span class="line">            &#125;);           </span><br><span class="line"><span class="javascript">            $(<span class="string">&quot;.bimg&gt;img&quot;</span>).css(&#123;         </span></span><br><span class="line"><span class="javascript">                left:-nx*$(<span class="string">&quot;.bimg&quot;</span>).width()/$(<span class="string">&quot;#move&quot;</span>).width()+<span class="string">&quot;px&quot;</span>,   </span></span><br><span class="line"><span class="javascript">                top:-ny*$(<span class="string">&quot;.bimg&quot;</span>).height()/$(<span class="string">&quot;#move&quot;</span>).height()+<span class="string">&quot;px&quot;</span>      </span></span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;)</span><br><span class="line">                                                      </span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    </span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>慕课网轮播图100%还原</title>
      <link href="front/js/jq-chatroom-prative/"/>
      <url>front/js/jq-chatroom-prative/</url>
      
        <content type="html"><![CDATA[<h3 id="骨架"><a href="#骨架" class="headerlink" title="骨架"></a>骨架</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span><span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;main&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./img/1.png&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./img/2.png&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./img/3.png&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./img/4.png&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./img/5.png&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./img/6.png&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:;&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;leftside&quot;</span> <span class="attr">class</span>=<span class="string">&quot;side&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:;&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;rightside&quot;</span> <span class="attr">class</span>=<span class="string">&quot;side&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span> <span class="attr">id</span>=<span class="string">&quot;ul&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;lili&#x27;</span> <span class="attr">name</span>=<span class="string">&quot;1&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;lili&#x27;</span> <span class="attr">name</span>=<span class="string">&quot;2&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;lili&#x27;</span> <span class="attr">name</span>=<span class="string">&quot;3&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;lili&#x27;</span> <span class="attr">name</span>=<span class="string">&quot;4&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;lili&#x27;</span> <span class="attr">name</span>=<span class="string">&quot;5&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;lili&#x27;</span> <span class="attr">name</span>=<span class="string">&quot;6&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;test&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="样式"><a href="#样式" class="headerlink" title="样式"></a>样式</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line">&lt;style type&#x3D;&quot;text&#x2F;css&quot;&gt;</span><br><span class="line">    img&#123;</span><br><span class="line">        position: absolute;</span><br><span class="line">        width: 936px;</span><br><span class="line">        height: 316px;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    .side&#123;</span><br><span class="line">        font-size: 25px;</span><br><span class="line">        position: absolute;</span><br><span class="line">        color: rgba(255, 255, 255, 0.6);</span><br><span class="line">        width: 36px;</span><br><span class="line">        height: 60px;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    .side:hover&#123;</span><br><span class="line">        background-color: rgba(7, 17, 27, 0.6);</span><br><span class="line">        border-radius: 3px;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    .side:only-child&#123;</span><br><span class="line">        height: 60px;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    #leftside&#123;</span><br><span class="line"></span><br><span class="line">        left: 10px;</span><br><span class="line">        top: 140px;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    #rightside&#123;</span><br><span class="line"></span><br><span class="line">        left: 906px;</span><br><span class="line">        top: 140px;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ul&#123;</span><br><span class="line">        list-style-type: none;</span><br><span class="line">        position: absolute;</span><br><span class="line">        left: 775px;</span><br><span class="line">        top: 270px;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    li&#123;</span><br><span class="line">        &#x2F;*position: ;*&#x2F;</span><br><span class="line">        float: left;</span><br><span class="line">        text-align: center;</span><br><span class="line">        cursor: pointer;</span><br><span class="line">        width: 18px;</span><br><span class="line">        height: 20px;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    .yuan&#123;</span><br><span class="line">        width: 20px;</span><br><span class="line">        height: 20px;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    #test&#123;</span><br><span class="line">        width: 20px;</span><br><span class="line">        height: 20px;</span><br><span class="line">        top: 100px;</span><br><span class="line">        left: 100px;</span><br><span class="line">        background-color: red;</span><br><span class="line">    &#125;</span><br><span class="line">&lt;&#x2F;style&gt;</span><br></pre></td></tr></table></figure><h3 id="脚本"><a href="#脚本" class="headerlink" title="脚本"></a>脚本</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">    var n &#x3D; 0;</span><br><span class="line">    function update_img(n) &#123;</span><br><span class="line">        &#x2F;&#x2F; 隐藏全部</span><br><span class="line">        $(&quot;#main&quot;).children().hide();</span><br><span class="line">        &#x2F;&#x2F;显示当前</span><br><span class="line">        $(&#39;#main&#39;).children().eq(n).fadeIn();</span><br><span class="line">        &#x2F;&#x2F; 更新变量</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F;更改函数</span><br><span class="line">    function change()&#123;</span><br><span class="line">        &#x2F;&#x2F; 设置次数</span><br><span class="line">        n &#x3D; n&gt;&#x3D;6?0:n;</span><br><span class="line">        update_img(n);</span><br><span class="line">        n++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    timer1 &#x3D; setInterval(change, 1500);</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F; 监听鼠标进入,清除定时器</span><br><span class="line">    $(&#39;#main&#39;).mouseenter(function () &#123;</span><br><span class="line">        clearInterval(timer1)</span><br><span class="line">    &#125;);</span><br><span class="line">    &#x2F;&#x2F; 监听鼠标离开,开启定时器</span><br><span class="line">    $(&#39;#main&#39;).mouseleave(function () &#123;</span><br><span class="line">        &#x2F;&#x2F; 实在整不出来,假装实现了</span><br><span class="line">        &#x2F;&#x2F; window.location.reload();</span><br><span class="line">        timer1 &#x3D; setInterval(change, 1500);</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F; 监听鼠标点击事件</span><br><span class="line">    $(&#39;#rightside&#39;).click(function () &#123;</span><br><span class="line">        n &#x3D; n&gt;&#x3D;6?0:n;</span><br><span class="line">        update_img(n);</span><br><span class="line">        n++;</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F; 监听鼠标点击事件</span><br><span class="line">    $(&#39;#leftside&#39;).click(function () &#123;</span><br><span class="line">        n &#x3D; n&lt;&#x3D;-1?6:n;</span><br><span class="line">        update_img(n);</span><br><span class="line">        n--;</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    for(var i&#x3D;0; i&lt;6; i++)&#123;</span><br><span class="line">        $(&#39;#ul&#39;).children().eq(i).click(function () &#123;</span><br><span class="line">        console.log(this);</span><br><span class="line">        m &#x3D; this.getAttribute(&quot;name&quot;);</span><br><span class="line">        console.log(m);</span><br><span class="line">        update_img(m-1);</span><br><span class="line">    &#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>linux版navicat安装和破解</title>
      <link href="database/navicat-linux/"/>
      <url>database/navicat-linux/</url>
      
        <content type="html"><![CDATA[<p><a href="https://blog.csdn.net/weixin_42844490/article/details/84134564">https://blog.csdn.net/weixin_42844490/article/details/84134564</a></p><p>工具环境：服务器CentOS7 64位（桌面版），本地windows10系统</p><p>在linux系统以原生命令为王的大背景下，能在其中运行windows窗口界面软件是件很开心、很有意义的事。</p><p>1.安装。</p><p>①先老实选择官方试用版安装（不推荐在各个下载平台去下载）</p><p>中文版：<a href="http://www.navicat.com.cn/download/navicat-for-mysql">http://www.navicat.com.cn/download/navicat-for-mysql</a></p><p>或英文版：<a href="https://www.navicat.com/en/download/navicat-for-mysql">https://www.navicat.com/en/download/navicat-for-mysql</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> navicat </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Eclipse IDE</title>
      <link href="ide/deepin-eclipse/"/>
      <url>ide/deepin-eclipse/</url>
      
        <content type="html"><![CDATA[<section>                <div class="before">                    <div class="other"><pre><code>                &lt;/div&gt;            &lt;/div&gt;            &lt;div class=&quot;new-box&quot;&gt;                &lt;div id=&quot;mw-content-text&quot; lang=&quot;zh-CN&quot; dir=&quot;ltr&quot; class=&quot;mw-content-ltr&quot;&gt;&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;&lt;div id=&quot;toctitle&quot;&gt;&lt;h3&gt;目录&lt;/h3&gt;&lt;/div&gt;</code></pre></div><h3><span class="mw-headline" id=".E7.AE.80.E4.BB.8B">简介</span></h3><p>Eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言，它只是一个框架和一组服务，用于通过插件组件构建开发环境。幸运的是，Eclipse 附带了一个标准的插件集，包括Java开发工具（Java Development Kit，JDK）。</p><h3><span class="mw-headline" id=".E5.AE.89.E8.A3.85">安装</span></h3><pre><code>sudo apt-get install eclipse-java   Eclipse IDE for Java EE Developerssudo apt-get install eclipse-jee    Eclipse IDE for Java Developerssudo apt-get install eclipse-cpp    Eclipse IDE for C/C++ Developerssudo apt-get install eclipse-php     Eclipse for PHP Developerssudo apt-get install eclipse-android    Eclipse for Android Developerssudo apt-get install eclipse-committers    Eclipse IDE for Eclipse Committerssudo apt-get install eclipse-javascript    Eclipse IDE for JavaScript and Web Developerssudo apt-get install eclipse-reporting     Eclipse IDE for Java and Report Developerssudo apt-get install eclipse-dsl        Eclipse IDE for Java and DSL Developerssudo apt-get install eclipse-rcp        Eclipse for RCP and RAP Developerssudo apt-get install eclipse-modeling     Eclipse Modeling Toolssudo apt-get install eclipse-parallel     Eclipse for Parallel Application Developerssudo apt-get install eclipse-testing      Eclipse for Testerssudo apt-get install eclipse-scout        Eclipse for Scout Developers</code></pre><h3><span class="mw-headline" id=".E5.8D.B8.E8.BD.BD">卸载</span></h3><pre><code>sudo apt-get remove eclipse-javasudo apt-get remove eclipse-jee sudo apt-get remove eclipse-cppsudo apt-get remove eclipse-phpsudo apt-get remove eclipse-androidsudo apt-get remove eclipse-committerssudo apt-get remove eclipse-javascriptsudo apt-get remove eclipse-reportingsudo apt-get remove eclipse-dslsudo apt-get remove eclipse-rcpsudo apt-get remove eclipse-modelingsudo apt-get remove eclipse-parallelsudo apt-get remove eclipse-testingsudo apt-get remove eclipse-scout</code></pre><h3><span class="mw-headline" id=".E4.BB.93.E5.BA.93.E5.9C.B0.E5.9D.80">仓库地址</span></h3><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-java/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-java/">http://packages.deepin.com/deepin/pool/main/e/eclipse-java/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-java/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-jee/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-jee/">http://packages.deepin.com/deepin/pool/main/e/eclipse-jee/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-jee/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-cpp/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-cpp/">http://packages.deepin.com/deepin/pool/main/e/eclipse-cpp/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-cpp/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-php/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-php/">http://packages.deepin.com/deepin/pool/main/e/eclipse-php/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-php/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-android/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-android/">http://packages.deepin.com/deepin/pool/main/e/eclipse-android/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-android/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-committers/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-committers/">http://packages.deepin.com/deepin/pool/main/e/eclipse-committers/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-committers/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-javascript/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-javascript/">http://packages.deepin.com/deepin/pool/main/e/eclipse-javascript/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-javascript/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-reporting/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-reporting/">http://packages.deepin.com/deepin/pool/main/e/eclipse-reporting/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-reporting/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-dsl/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-dsl/">http://packages.deepin.com/deepin/pool/main/e/eclipse-dsl/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-dsl/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-rcp/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-rcp/">http://packages.deepin.com/deepin/pool/main/e/eclipse-rcp/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-rcp/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-modeling/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-modeling/">http://packages.deepin.com/deepin/pool/main/e/eclipse-modeling/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-modeling/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-parallel/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-parallel/">http://packages.deepin.com/deepin/pool/main/e/eclipse-parallel/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-parallel/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-testing/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-testing/">http://packages.deepin.com/deepin/pool/main/e/eclipse-testing/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-testing/"></a></p><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-scout/"></a><a href="http://packages.deepin.com/deepin/pool/main/e/eclipse-scout/">http://packages.deepin.com/deepin/pool/main/e/eclipse-scout/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/e/eclipse-scout/"></a></p><h3><span class="mw-headline" id=".E5.B8.B8.E8.A7.81.E9.97.AE.E9.A2.98">常见问题</span></h3><h3><span class="mw-headline" id=".E7.9B.B8.E5.85.B3.E9.93.BE.E6.8E.A5">相关链接</span></h3><p>维基百科：</p><!-- NewPP limit reportCached time: 20190903053301Cache expiry: 86400Dynamic content: falseCPU time usage: 0.008 secondsReal time usage: 0.010 secondsPreprocessor visited node count: 1/1000000Preprocessor generated node count: 4/1000000Post‐expand include size: 0/2097152 bytesTemplate argument size: 0/2097152 bytesHighest expansion depth: 1/40Expensive parser function count: 0/100--><!-- Transclusion expansion time report (%,ms,calls,template)100.00%    0.000      1 - -total--><!-- Saved in parser cache with key mediawiki:pcache:idhash:230-0!*!*!!zh-cn!*!* and timestamp 20190903053301 and revision id 608 --></div>                </div>            </section>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Visual Studio Code简介</title>
      <link href="ide/deepin-vscode/"/>
      <url>ide/deepin-vscode/</url>
      
        <content type="html"><![CDATA[<section>                <div class="before">                    <div class="other">                    </div>                </div>                <div class="new-box">                    <div id="mw-content-text" lang="zh-CN" dir="ltr" class="mw-content-ltr"><div id="toc" class="toc"><div id="toctitle"><h3>目录</h3></div></div><h3><span class="mw-headline" id=".E7.AE.80.E4.BB.8B">简介</span></h3><p>Visual Studio Code是一款轻量级代码编辑器，它具有语法高亮、可定制的热键绑定、括号匹配、代码片段收集、代码调试、自定义语言和主题、支持扩展/插件等功能。</p><h3><span class="mw-headline" id=".E5.AE.89.E8.A3.85">安装</span></h3><p><code>sudo apt-get install vscode</code></p><h3><span class="mw-headline" id=".E5.8D.B8.E8.BD.BD">卸载</span></h3><p><code>sudo apt-get remove vscode</code></p><h3><span class="mw-headline" id=".E4.BB.93.E5.BA.93.E5.9C.B0.E5.9D.80">仓库地址</span></h3><p><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/v/vscode/"></a><a href="http://packages.deepin.com/deepin/pool/main/v/vscode/">http://packages.deepin.com/deepin/pool/main/v/vscode/</a><a rel="nofollow" class="external text" href="http://packages.deepin.com/deepin/pool/main/v/vscode/"></a></p><h3><span class="mw-headline" id=".E5.B8.B8.E8.A7.81.E9.97.AE.E9.A2.98">常见问题</span></h3><h3><span class="mw-headline" id=".E7.9B.B8.E5.85.B3.E9.93.BE.E6.8E.A5">相关链接</span></h3><p>维基百科：</p><!-- NewPP limit reportCached time: 20190903044709Cache expiry: 86400Dynamic content: falseCPU time usage: 0.008 secondsReal time usage: 0.006 secondsPreprocessor visited node count: 1/1000000Preprocessor generated node count: 4/1000000Post‐expand include size: 0/2097152 bytesTemplate argument size: 0/2097152 bytesHighest expansion depth: 1/40Expensive parser function count: 0/100--><!-- Transclusion expansion time report (%,ms,calls,template)100.00%    0.000      1 - -total--><!-- Saved in parser cache with key mediawiki:pcache:idhash:224-0!*!*!!zh-cn!*!* and timestamp 20190903044709 and revision id 428 --></div>                </div></section>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ide </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Deepin 搭建php开发环境</title>
      <link href="php/deepin-install-xampp/"/>
      <url>php/deepin-install-xampp/</url>
      
        <content type="html"><![CDATA[<section>                <div class="before">                    <div class="other">                    </div>                </div>                <div class="new-box">                    <div id="mw-content-text" lang="zh-CN" dir="ltr" class="mw-content-ltr"><div id="toc" class="toc"><div id="toctitle"><h3>目录</h3></div></div><h1><span class="mw-headline" id=".E7.AE.80.E4.BB.8B">简介</span></h1><p>本词条意在说明如何快速简便地搭建php开发环境。</p><h1><span class="mw-headline" id=".E6.AD.A3.E6.96.87">正文</span></h1><p>XAMPP是一个把Apache网页服务器与PHP、Perl,phpMyAdmin及MariaDB集合在一起的安装包，允许用户可以在自己的电脑上轻易的建立网页服务器。  -- 百科</p><h3><span class="mw-headline" id=".E5.AE.89.E8.A3.85">安装</span></h3><p>下载地址： <a rel="nofollow" class="external free" href="https://www.apachefriends.org">https://www.apachefriends.org</a></p><p>我们需要选择XAMPP for linux。此处以xampp-linux-x64-7.3.1-0-installer.run为例进行说明。</p><p>下载到本地后，打开安装包所在文件夹，在文件夹空白处右击鼠标选择在终端中打开。然后在终端中执行以下命令：</p><pre><code>    $ sudo ./xampp-linux-x64-7.3.1-0-installer.run</code></pre><p>如果提示没有这个命令,则是权限不足,执行:</p><pre><code>    $ sudo chmod 777 xampp-linux-x64-7.3.1-0-installer.run</code></pre><p>然后重新执行上述命令即可</p><p>该命令执行后，xampp图形化安装程序便会启动，根据提示安装即可。</p><h3><span class="mw-headline" id=".E5.BC.80.E5.90.AFxampp">开启xampp</span></h3><p>1）安装完成之后， 程序会自动运行，此时需要手动点击进入manage server界面，点击启动全部选项。</p><p>2）在Deepin系统中，XAMPP程序没有图标，故在日常使用时，需要通过命令行启动。命令行如下</p><p>$ sudo ./opt/lampp/lampp start         启动</p><p>$ sudo ./opt/lampp/lampp restart     重启</p><p>$ sudo ./opt/lampp/lampp stop         停止</p><h3><span class="mw-headline" id=".E6.B5.8B.E8.AF.95.E6.98.AF.E5.90.A6.E6.88.90.E5.8A.9F">测试是否成功</span></h3><p>打开浏览器，在地址栏输入localhost，能打开welcome to xampp网页</p><p>打开浏览器，在地址栏输入localhost、phpmyadmin，能打开phpmyadmin管理网页</p><p>以上两项均无问题则说明本次环境搭建成功</p><h3><span class="mw-headline" id=".E5.A6.82.E4.BD.95.E4.BD.BF.E7.94.A8.E8.AF.A5.E7.8E.AF.E5.A2.83.E5.BC.80.E5.8F.91PHP.E7.A8.8B.E5.BA.8F">如何使用该环境开发PHP程序</span></h3><p>在确保XAMPP成功安装并已启动后，可使用命令行在指定文件夹创建php文件</p><p>$ sudo touch /opt/lampp/htdocs/name.php</p><p>此处在opt/lampp/htdocs文件夹下创建了一个名为name的php程序</p><p>！！！需要注意的事，在opt/lampp/apache2文件夹下也有一个htdocs文件夹，在此文件夹下创建的php文件并不能在浏览器中打开。</p><p>！！！只有opt/lampp文件夹下的htdocs文件夹里的php文件能被浏览器打开</p><h3><span class="mw-headline" id="PHP.E7.BC.96.E8.BE.91.E5.99.A8.E6.8E.A8.E8.8D.90">PHP编辑器推荐</span></h3><p>在Deepin系统中可以方便地使用Sublime Text编辑器进行php的编辑</p><!-- NewPP limit reportCached time: 20190903053453Cache expiry: 86400Dynamic content: falseCPU time usage: 0.004 secondsReal time usage: 0.006 secondsPreprocessor visited node count: 1/1000000Preprocessor generated node count: 4/1000000Post‐expand include size: 0/2097152 bytesTemplate argument size: 0/2097152 bytesHighest expansion depth: 1/40Expensive parser function count: 0/100--><!-- Transclusion expansion time report (%,ms,calls,template)100.00%    0.000      1 - -total--><!-- Saved in parser cache with key mediawiki:pcache:idhash:457-0!*!*!!zh-cn!*!* and timestamp 20190903053453 and revision id 1784 --></div>                </div>            </section>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> deepin </tag>
            
            <tag> php </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JS之DOM思维导图</title>
      <link href="front/js/js-dom-mind-mapping/"/>
      <url>front/js/js-dom-mind-mapping/</url>
      
        <content type="html"><![CDATA[<p><img src= "/img/loading.gif" data-lazy-src="/img/posts/js/js_dom_xmind_mapping.gif" alt="js dom xmind pic"></p>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Deepin下java开发环境部署</title>
      <link href="java/javase/deepin-install-jdk/"/>
      <url>java/javase/deepin-install-jdk/</url>
      
        <content type="html"><![CDATA[<section>                <div class="before">                    <div class="other"><pre><code>                &lt;/div&gt;            &lt;/div&gt;            &lt;div class=&quot;new-box&quot;&gt;                &lt;div id=&quot;mw-content-text&quot; lang=&quot;zh-CN&quot; dir=&quot;ltr&quot; class=&quot;mw-content-ltr&quot;&gt;&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;&lt;div id=&quot;toctitle&quot;&gt;&lt;h3&gt;目录&lt;/h3&gt;&lt;/div&gt;</code></pre></div><h3><span class="mw-headline" id=".E7.AE.80.E4.BB.8B">简介</span></h3><p>本经验由深度论坛用户(zhang12345shun)分享，<a rel="nofollow" class="external text" href="https://bbs.deepin.org/forum.php?mod=viewthread&amp;tid=36225">原文地址</a></p><h3><span class="mw-headline" id=".E6.AD.A3.E6.96.87">正文</span></h3><h3><span class="mw-headline" id="SUN_JDK.EF.BC.88.E7.8E.B0.E5.B7.B2.E6.94.B9.E5.90.8DOracle_JDK.EF.BC.89">SUN JDK（现已改名Oracle JDK）</span></h3><p>1.下载Sun版JDK压缩包（.tar.gz），选择其中的32/64位Linux版本。</p><p>2.将其解压缩：</p><p><code>sudo tar -zxvf ~/Downloads/jdk-8u45-linux-i586.tar.gz -C /usr/lib</code> </p><p>其中参数-C后面的路径是解压缩的目标路径。</p><p>3.根据官网的说法：</p><blockquote><p>Starting with version 8u40, the JDK installation is integrated with the alternatives framework and after installation, the alternatives framework is updated to reflect the binaries from the recently installed JDK. Java commands such as java, javac, javadoc, and javap can be invoked from the command line.  </p></blockquote><p>所以：</p><pre><code>sudo update-alternatives --install /usr/bin/java java  /usr/lib/jdk1.8.0_66/bin/java 1000 sudo update-alternatives --install /usr/bin/javac javac  /usr/lib/jdk1.8.0_66/bin/javac 1000</code></pre><p>现在可以验证一下JDK安装是否已成功 </p><p><code>java -version</code></p><h3><span class="mw-headline" id="tomact_.E5.AE.89.E8.A3.85.E5.92.8C.E4.BD.BF.E7.94.A8">tomact 安装和使用</span></h3><p>1.下载并解压缩到部署位置(8.0.30)</p><p>2.配置环境变量</p><p><code>startup.sh-----&gt;catalina.sh-----&gt;setclassspath.shJAVA_HOME=/usr/lib/jdk1.8.0_66JRE_HOME=$JAVA_HOME/jre</code></p><ul><li>备注：这里的配置可以不写（如果jdk是8u40及以后版本） </li></ul><p>3.启动tomcat： </p><p><code>sudo ./bin/startup.sh</code></p><p>4.关闭tomcat： </p><p><code>sudo ./bin/shutdown.sh</code></p><p>5.最后，验证tomcat关闭是否成功：</p><p>在浏览器中输入：<a rel="nofollow" class="external free" href="http://localhost:8080/">http://localhost:8080/</a></p><h3><span class="mw-headline" id="MYSQL.E5.AE.89.E8.A3.85.E5.92.8C.E4.BD.BF.E7.94.A8">MYSQL安装和使用</span></h3><p>1.下载并解压缩 </p><p><code>sudo tar -xzvf mysql-6.0.11-alpha-linux-x86_64-glibc23.tar.gz -C destdir</code></p><p>2.新增用户mysql和组mysql </p><pre><code>sudo groupadd mysql sudo useradd -g mysql mysql</code></pre><p>3.创建链接 </p><pre><code>cd /usr/local sudo ln -s /opt/mysql-6.0.11-alpha-linux-x86_64-glibc23/ mysql</code></pre><p>4.改变mysql文件夹own group </p><pre><code>sudo chown -R mysql . sudo chgrp -R mysql .</code></pre><p>5.执行初始化脚本 </p><p><code>scripts/mysql_install_db –user=mysql</code></p><p>6.改变文件夹权限 </p><pre><code>chown -R root . chown -R mysql data</code></pre><p>7.配置mysql环境 </p><p>使用自带的配置文件复制到/etc 目录下比如：</p><p><code>cp support-files/my-medium.cnf /etc/my.cnf</code></p><p>根据内存不同使用不同的配置文件。一般建议使用 </p><p><strong> my-larger.cnf </strong> </p><ul><li>说明：会占用系统内存512M，运行主要的进行。</li></ul><p><strong> my-medium.cnf </strong> </p><ul><li>说明：mysql平时只占用系统内存在【32M～64M】之间，或者和其他程序一起工作时比如 web server .占用内存不会超过128M </li></ul><p><strong> my-small.cnf </strong> </p><ul><li>说明：只占用系统的很小内存（&lt;=64M）,只运行重要的守护进程。不会占用太多的资源 </li></ul><p>8.启动服务 </p><pre><code>bin/mysqld_safe –user=mysql &amp; //启动服务 bin/mysqladmin -u root password ‘new_password’ //初始化root密码</code></pre><p>9.开机自启动 </p><p>复制服务脚本&nbsp;: <code>cp support-files/mysql.server /etc/init.d/mysql</code></p><p>取消自启动:<code>sudo update-rc.d -f mysql.server remove</code></p><p>把 /usr/local/mysql/bin/mysql 命令加到用户命令中 </p><p><code>sudo ln -s /usr/local/mysql/bin/mysql /usr/local/bin/mysql</code></p><p>现在就直接可以使用 mysql 命令了 </p><p><code>mysql -u root -p</code></p><h3><span class="mw-headline" id="Eclipse_.E5.AE.89.E8.A3.85.E4.BD.BF.E7.94.A8">Eclipse 安装使用</span></h3><p>1.安装JDK8，具体过程参考上面2.下载 Eclipse 最新版http://www.eclipse.org/downloads/ </p><p>解压 Eclipse:</p><p><code>sudo tar -zxvf ~/Downloads/eclipse-*.tar.gz</code></p><p>3.创建 Eclipse 快捷方式 </p><p>在终端中执行如下命令 </p><p><code>sudo gedit /usr/share/applications/eclipse.desktop</code></p><p>粘贴并保存如下内容 </p><pre><code>[Desktop Entry] Type=Application Name=Eclipse Comment=Eclipse Integrated Development Environment Icon=eclipse Exec=/opt/eclipse/eclipse Terminal=false Categories=Development;IDE;Java; </code></pre><p>至此，我们就将最新版本的 Eclipse 安装完成</p><h3><span class="mw-headline" id="MAVEN.E5.AE.89.E8.A3.85">MAVEN安装</span></h3><p>1.下载并加压包到安装位置 exp:/usr/local/</p><p>2.配置命令连接符</p><p><code>sudo update-alternatives --install /usr/bin/mvn mvn /opt/apache-maven-3.3.9/bin/mvn 1000</code></p><p>3.配置默认jdk版本和默认编译级别在目录conf/setting.xml中配置</p><pre><code>&lt;profile&gt;    &lt;id&gt;jdk-1.8&lt;/id&gt;    &lt;activation&gt;        &lt;activeByDefault&gt;true&lt;/activeByDefault&gt;        &lt;jdk&gt;1.8&lt;/jdk&gt;    &lt;/activation&gt;    &lt;properties&gt;              &lt;maven.compiler.source&gt;1.8&lt;/maven.compiler.source&gt;        &lt;maven.compiler.target&gt;1.8&lt;/maven.compiler.target&gt;                    &lt;maven.compiler.compilerVersion&gt;1.8&lt;/maven.compiler.compilerVersion&gt;    &lt;/properties&gt;&lt;/profile&gt;</code></pre><!-- NewPP limit reportCached time: 20190903123746Cache expiry: 86400Dynamic content: falseCPU time usage: 0.008 secondsReal time usage: 0.009 secondsPreprocessor visited node count: 1/1000000Preprocessor generated node count: 4/1000000Post‐expand include size: 0/2097152 bytesTemplate argument size: 0/2097152 bytesHighest expansion depth: 1/40Expensive parser function count: 0/100--><!-- Transclusion expansion time report (%,ms,calls,template)100.00%    0.000      1 - -total--><!-- Saved in parser cache with key mediawiki:pcache:idhash:471-0!*!*!!zh-cn!*!* and timestamp 20190903123746 and revision id 1689 --></div>                </div>            </section>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> deepin </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>ubuntu系统下Java环境JDK的安装</title>
      <link href="java/javase/ubuntu-install-jdk/"/>
      <url>java/javase/ubuntu-install-jdk/</url>
      
        <content type="html"><![CDATA[<h3 id="Debian-Linux下安装jdk"><a href="#Debian-Linux下安装jdk" class="headerlink" title="Debian Linux下安装jdk"></a>Debian Linux下安装jdk</h3><h3 id="下载压缩包"><a href="#下载压缩包" class="headerlink" title="下载压缩包"></a>下载压缩包</h3><p>官网下载对应的.gz包 <a href="https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html">点击下载</a></p><h3 id="解压文件"><a href="#解压文件" class="headerlink" title="解压文件"></a>解压文件</h3><p>创建一个目录用于存放解压后的文件，并解压缩到该目录下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo mkdir  &#x2F;opt&#x2F;java8</span><br><span class="line">sudo tar -zxvf jdk-8u221-linux-x64.tar.gz -C  &#x2F;opt&#x2F;java8</span><br></pre></td></tr></table></figure><h3 id="修改环境变量"><a href="#修改环境变量" class="headerlink" title="修改环境变量"></a>修改环境变量</h3><p><code>sudo vim ~/.bashrc</code></p><h3 id="进入文件，末尾追加如下内容："><a href="#进入文件，末尾追加如下内容：" class="headerlink" title="进入文件，末尾追加如下内容："></a>进入文件，末尾追加如下内容：</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">export JAVA_HOME&#x3D;&#x2F;opt&#x2F;java8&#x2F;jdk1.8.0_221      &#x2F;&#x2F;这里要注意目录要换成自己解压的jdk目录</span><br><span class="line">export JRE_HOME&#x3D;$&#123;JAVA_HOME&#125;&#x2F;jre  </span><br><span class="line">export CLASSPATH&#x3D;.:$&#123;JAVA_HOME&#125;&#x2F;lib:$&#123;JRE_HOME&#125;&#x2F;lib  </span><br><span class="line">export PATH&#x3D;$&#123;JAVA_HOME&#125;&#x2F;bin:$PATH</span><br><span class="line">&#96;&#96;&#96;    </span><br><span class="line">### 使环境变量生效</span><br></pre></td></tr></table></figure><p>source ~/.bashrc</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">### 设置系统默认jdk</span><br></pre></td></tr></table></figure><p>sudo update-alternatives –install /usr/bin/java java /opt/java8/jdk1.8.0_211/bin/java 300<br>sudo update-alternatives –install /usr/bin/javac javac /opt/java8/jdk1.8.0_211/bin/javac 300<br>sudo update-alternatives –install /usr/bin/jar jar /opt/java8/jdk1.8.0_211/bin/jar 300<br>sudo update-alternatives –install /usr/bin/javah javah /opt/java8/jdk1.8.0_211/bin/javah 300<br>sudo update-alternatives –install /usr/bin/javap javap /opt/java8/jdk1.8.0_211/bin/javap 300</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">然后执行：</span><br></pre></td></tr></table></figure><p>sudo update-alternatives –config java</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">### 测试是否安装成功</span><br></pre></td></tr></table></figure><p>java -version</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">### 突发情况</span><br><span class="line">Ubuntu的桌面不显示任何的快捷方式，而且不能往桌面上移动文件和目录。最简单的是重载桌面。 进入终端，执行以下命令：</span><br></pre></td></tr></table></figure><p>sudo apt-get update<br>sudo apt-get install –reinstall ubuntu-desktop<br>sudo apt-get install unity<br>sudo shutdown -r now<br>```</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> ubuntu </tag>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>CSS中input和button对齐的解决方案</title>
      <link href="front/css/input-button-alignment/"/>
      <url>front/css/input-button-alignment/</url>
      
        <content type="html"><![CDATA[<h3 id="问题简析"><a href="#问题简析" class="headerlink" title="问题简析"></a>问题简析</h3><p>在html中,input标签和button经常一起使用,让用户输入一些内容<br>但是在默认的布局中,input标签和button标签会出现对不齐的现象<br>这会导致页面的样式不会很好看,如何解决这个问题呢<br>这里我们可以将button 的 position设置为absolute就行了</p><h3 id="参考"><a href="#参考" class="headerlink" title="参考:"></a>参考:</h3><p><a href="https://www.cnblogs.com/ruanxh123/p/5658868.html">输入框input和旁边按钮对齐的解决方案</a>  <a href="https://www.jb51.net/css/154229.html">CSS如何对齐文本框和其旁边的图像按钮比如搜索框等等</a><br><a href="https://blog.csdn.net/MrZZhou/article/details/72757936">input type为text和button的不对齐问题 以及 之间的小空格</a><br><a href="https://blog.csdn.net/liaobc/article/details/6137770">文本框和按钮对齐</a>  </p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> css </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>node+socket+jq 实现简易聊天室</title>
      <link href="front/node/node-socket-chatroom/"/>
      <url>front/node/node-socket-chatroom/</url>
      
        <content type="html"><![CDATA[<p>直接上代码</p><h3 id="前台部分（client-html"><a href="#前台部分（client-html" class="headerlink" title="前台部分（client.html)"></a>前台部分（client.html)</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!doctype <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">content</span>=<span class="string">&quot;width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--    导入socket.io--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;http://wulv5.com/js/socket.io.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;main&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;title&quot;</span>&gt;</span></span><br><span class="line">        花里胡哨的聊天室</span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">id</span>=<span class="string">&quot;shuru&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> <span class="attr">id</span>=<span class="string">&quot;btn&quot;</span>&gt;</span>send it<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;record&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"></span><br><span class="line">*&#123;</span><br><span class="line"><span class="css"><span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="css"><span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="css"><span class="attribute">font-size</span>: <span class="number">100%</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">#main&#123;</span><br><span class="line"><span class="css">    <span class="attribute">width</span>: <span class="number">800px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">margin</span>: <span class="number">0</span> auto;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">#title&#123;</span><br><span class="line"><span class="css">    <span class="attribute">width</span>: <span class="number">700px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">font-size</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">color</span>: deeppink;</span></span><br><span class="line"><span class="css">    <span class="attribute">margin</span>: <span class="number">0</span> auto;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">#shuru&#123;</span><br><span class="line"><span class="css">    <span class="attribute">position</span>: relative;</span></span><br><span class="line"><span class="css">    <span class="attribute">width</span>: <span class="number">500px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">height</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">margin</span>: <span class="number">0</span> auto;</span></span><br><span class="line"><span class="css">    <span class="attribute">font-size</span>: <span class="number">45px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">border-radius</span>: <span class="number">15px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">border</span>: <span class="number">2px</span> solid lightsalmon;</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">#btn&#123;</span><br><span class="line"><span class="css">    <span class="attribute">height</span>: <span class="number">55px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">font-size</span>: <span class="number">30px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">background-color</span>: greenyellow;</span></span><br><span class="line"><span class="css">    <span class="attribute">margin</span>: auto auto;</span></span><br><span class="line"><span class="css">    <span class="attribute">border-radius</span>: <span class="number">15px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">text-align</span>: left;</span></span><br><span class="line"><span class="css">    <span class="attribute">border</span>: <span class="number">2px</span> solid lightsalmon;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">.son&#123;</span><br><span class="line"></span><br><span class="line"><span class="css">    <span class="attribute">border</span>: <span class="number">1px</span> solid lightsalmon;</span></span><br><span class="line"><span class="css">    <span class="attribute">font-size</span>: <span class="number">30px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">background-color</span>: blueviolet;</span></span><br><span class="line"><span class="css">    <span class="attribute">color</span>: <span class="number">#ffffff</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">border-radius</span>: <span class="number">15px</span>;</span></span><br><span class="line"><span class="css">    <span class="attribute">width</span>: <span class="number">600px</span>;</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="javascript">    <span class="comment">// 链接聊天室的io服务器</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> socket = io.connect(<span class="string">&#x27;/&#x27;</span>);</span></span><br><span class="line"><span class="javascript">    <span class="comment">// 监听点击事件</span></span></span><br><span class="line"><span class="javascript">    $(<span class="string">&#x27;#btn&#x27;</span>).click(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">        socket.send($(<span class="string">&#x27;#shuru&#x27;</span>).val());</span></span><br><span class="line"><span class="javascript">        $(<span class="string">&#x27;#shuru&#x27;</span>).val(<span class="string">&#x27;&#x27;</span>);</span></span><br><span class="line">    &#125;);</span><br><span class="line"><span class="javascript">    <span class="comment">// 输出服务端返回的信息</span></span></span><br><span class="line"><span class="javascript">    socket.on(<span class="string">&#x27;message&#x27;</span>, <span class="function"><span class="keyword">function</span> (<span class="params">mes</span>) </span>&#123;</span></span><br><span class="line"><span class="handlebars"><span class="xml">        content = &#x27;<span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;son&quot;</span>&gt;</span>&#x27; + &#x27;<span class="symbol">&amp;nbsp;</span><span class="symbol">&amp;nbsp;</span>&#x27; +mes + &quot;<span class="tag">&lt;<span class="name">br</span>&gt;</span>&quot;+&#x27;<span class="tag">&lt;/<span class="name">div</span>&gt;</span>&#x27;;</span></span></span><br><span class="line"><span class="javascript">        $(<span class="string">&#x27;#record&#x27;</span>).append(content);</span></span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="后台部分-server-js"><a href="#后台部分-server-js" class="headerlink" title="后台部分(server.js)"></a>后台部分(server.js)</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> http = <span class="built_in">require</span>(<span class="string">&#x27;http&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> ws = <span class="built_in">require</span>(<span class="string">&#x27;socket.io&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> server = http.createServer(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> html = fs.readFileSync(<span class="string">&#x27;./client.html&#x27;</span>);</span><br><span class="line">    res.end(html);</span><br><span class="line">&#125;).listen(<span class="number">1998</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> io = ws(server);</span><br><span class="line"></span><br><span class="line">io.on(<span class="string">&#x27;connection&#x27;</span>,<span class="function"><span class="keyword">function</span> (<span class="params">socket</span>) </span>&#123;</span><br><span class="line">    socket.on(<span class="string">&#x27;message&#x27;</span>,<span class="function"><span class="keyword">function</span> (<span class="params">obj</span>) </span>&#123;</span><br><span class="line">        io.emit(<span class="string">&#x27;message&#x27;</span>, obj)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><h3 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h3><p><code>node server.js</code></p><h3 id="访问"><a href="#访问" class="headerlink" title="访问"></a>访问</h3><p>在本机的ip地址中访问本地服务器即可<br><code>http://127.0.0.1:1998/</code></p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/node/chatroom.png" alt="chatroom"></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> node </tag>
            
            <tag> web </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>GitHub上那些奇葩项目</title>
      <link href="git/github-special-projects/"/>
      <url>git/github-special-projects/</url>
      
        <content type="html"><![CDATA[<h2 id="GitHub上那些奇葩”项目”"><a href="#GitHub上那些奇葩”项目”" class="headerlink" title="GitHub上那些奇葩”项目”"></a>GitHub上那些奇葩”项目”</h2><h3 id="Dress-女装大佬聚集地"><a href="#Dress-女装大佬聚集地" class="headerlink" title="Dress - 女装大佬聚集地"></a>Dress - 女装大佬聚集地</h3><p>有129名贡献者在这个名为Dress的项目里集结，上传了数千张女装照，收获了8000余颗星。</p><p>你敢相信这是个码农？</p><p>地址：<a href="https://github.com/komeiji-satori/Dress">https://github.com/komeiji-satori/Dress</a></p><h3 id="Thanos-灭霸命令"><a href="#Thanos-灭霸命令" class="headerlink" title="Thanos - 灭霸命令"></a>Thanos - 灭霸命令</h3><p>Thanos.sh是一个开源的个灭霸命令，可随机删除电脑上一半文件。</p><p>地址：<a href="https://github.com/hotvulcan/Thanos.sh">https://github.com/hotvulcan/Thanos.sh</a></p><h3 id="nocode-一行代码都没有"><a href="#nocode-一行代码都没有" class="headerlink" title="nocode - 一行代码都没有"></a>nocode - 一行代码都没有</h3><p>这是一个Issue比项目更精彩的项目，项目中一行代码都没有，Issue中各种装逼。</p><p>想问下，Star这个项目的2.7万人是有多无聊？？？</p><p>地址：<br><a href="https://github.com/kelseyhightower/nocode">https://github.com/kelseyhightower/nocode</a></p><h3 id="programmer-job-blacklist-码农找工作黑名单"><a href="#programmer-job-blacklist-码农找工作黑名单" class="headerlink" title="programmer-job-blacklist 码农找工作黑名单"></a>programmer-job-blacklist 码农找工作黑名单</h3><p>地址：<a href="https://github.com/shengxinjing/programmer-job-blacklist">https://github.com/shengxinjing/programmer-job-blacklist</a></p><h3 id="hangzhou-house-knowledge-杭州买房攻略"><a href="#hangzhou-house-knowledge-杭州买房攻略" class="headerlink" title="hangzhou_house_knowledge 杭州买房攻略"></a>hangzhou_house_knowledge 杭州买房攻略</h3><p>地址：<a href="https://github.com/houshanren/hangzhou_house_knowledge">https://github.com/houshanren/hangzhou_house_knowledge</a></p><h3 id="howmanypeoplearearound-通过-Wi-Fi-信号估计附近有多少人"><a href="#howmanypeoplearearound-通过-Wi-Fi-信号估计附近有多少人" class="headerlink" title="howmanypeoplearearound 通过 Wi-Fi 信号估计附近有多少人"></a>howmanypeoplearearound 通过 Wi-Fi 信号估计附近有多少人</h3><p>地址：<br><a href="https://github.com/schollz/howmanypeoplearearound">https://github.com/schollz/howmanypeoplearearound</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>各大AI开放平台一览</title>
      <link href="unclass/ai.xxx.com/"/>
      <url>unclass/ai.xxx.com/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「简简单单OnlineZuozuo」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。<br>原文链接：<a href="https://blog.csdn.net/qq_15071263/article/details/82908201%E3%80%81">https://blog.csdn.net/qq_15071263/article/details/82908201、</a></p><div id="content_views" class="markdown_views prism-tomorrow-night-eighties">                    <!-- flowchart 箭头图标 勿删 -->                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                    </svg>                                            <p></p><div class="toc"><h3><a name="t0"></a>文章目录</h3><ul><li><a href="#AI__2" rel="nofollow" data-token="54290a69595c2c4d3a7c62273378fc4c" target="_self">各大AI 开放平台一览</a></li><ul><li><a href="#2019_7" rel="nofollow" data-token="bd560edff6a0011339a54dc6b6388579" target="_self">传送门：2019世界人工智能大会</a></li><ul><ul><ul><li><a href="#1AI_15" rel="nofollow" data-token="7038d139e539a57315ec4bff9d9690fa" target="_self">1、百度AI</a></li><li><a href="#2AI__19" rel="nofollow" data-token="c7088db383f3b97f56d3097560d69d28" target="_self">2、腾讯AI 开放平台</a></li><li><a href="#3_24" rel="nofollow" data-token="48c1bc8278e416be7472e6f0f24d1714" target="_self">3、阿里人工智能</a></li><li><a href="#4_29" rel="nofollow" data-token="b1dee4a1283b958863689317b1d9aa21" target="_self">4、网易人工智能</a></li><li><a href="#5_33" rel="nofollow" data-token="27d36132aba5ac61b349da209ae58e3a" target="_self">5、亚马逊人工智能服务</a></li><li><a href="#6Inter__36" rel="nofollow" data-token="be7b02cc21773efd0f92d29e8f0e4cb8" target="_self">6、Inter 英特尔人工智能服务</a></li></ul></ul><li><a href="#2019325__41" rel="nofollow" data-token="258944d88c9b69e7c90117e3fce54242" target="_self">2019年3月25日 更新</a></li><ul><ul><li><a href="#1AI_42" rel="nofollow" data-token="0eb5979a8c45a31d000927c66bfc87cc" target="_self">1、京东AI</a></li><li><a href="#2_AI_47" rel="nofollow" data-token="e610f9d4f332dadc167404b633bad575" target="_self">2、海康威视 AI</a></li><li><a href="#3Face_AI_55" rel="nofollow" data-token="8a9bee694fc78352ba4fcd95dc28c42d" target="_self">3、Face++ AI</a></li><li><a href="#4_AI_58" rel="nofollow" data-token="23cca1570bce223eb5f5deb6129ad1e2" target="_self">4、小米小爱 AI</a></li><li><a href="#5_AI_61" rel="nofollow" data-token="678fb8baef043c5bc550e5b73730cd40" target="_self">5、搜狗 AI</a></li><li><a href="#6OLAMI__AI_64" rel="nofollow" data-token="5feaafbe1bfb35d061cfe1017146778a" target="_self">6、OLAMI 欧拉密 AI</a></li><li><a href="#7_AI_68" rel="nofollow" data-token="6158c86e074eb13194f29c6acc9553ba" target="_self">7、讯飞 AI</a></li></ul></ul></ul></ul></ul></div><p></p><h1><a name="t1"></a><a id="AI__2"></a>各大AI 开放平台一览</h1><hr><h2><a name="t2"></a><a id="2019_7"></a>传送门：2019世界人工智能大会</h2><p><a href="https://wretchant.blog.csdn.net/article/details/100146938" rel="nofollow" data-token="54b4cc0f41875a34c52f2fb979f4c47e">传送门：2019世界人工智能大会</a></p><hr><h5><a id="1AI_15"></a>1、百度AI</h5><p><a href="http://ai.baidu.com/" rel="nofollow" data-token="418fc2689acc965f96c57e84da5da810">点击进入 AI 官网 </a><br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325134000922.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="2AI__19"></a>2、腾讯AI 开放平台</h5><p><a href="https://ai.qq.com/" rel="nofollow" data-token="90d2e478350800c102b2241d56d0d5b0">点击进入 AI 官网 </a></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325134012903.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="3_24"></a>3、阿里人工智能</h5><p><a href="https://open.bot.tmall.com/" rel="nofollow" data-token="222a4e3321a5161d53aec79cfb3bfe83">点击进入 AI 官网 </a></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325134027365.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="4_29"></a>4、网易人工智能</h5><p><a href="https://ai.163.com/#/m/overview" rel="nofollow" data-token="88fc8d4c43e2a6b10b63a7bc5e24dfa4">点击进入 AI 官网 </a></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325134044170.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="5_33"></a>5、亚马逊人工智能服务</h5><p><a href="https://amazonaws-china.com/cn/events/amazon-ai/" rel="nofollow" data-token="868c3b7459ab2822330d17e420b078dd">点击进入 AI  官网</a><br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325134109472.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="6Inter__36"></a>6、Inter 英特尔人工智能服务</h5><p><a href="https://software.intel.com/zh-cn/ai-academy/" rel="nofollow" data-token="308264cd2e32b65f6df03af5403cbd15">点击进入 AI 官网 </a></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325134128730.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h3><a name="t3"></a><a id="2019325__41"></a>2019年3月25日 更新</h3><h5><a id="1AI_42"></a>1、京东AI</h5><p><a href="http://neuhub.jd.com" rel="nofollow" data-token="cf1b3e3241e123da3a79a89f881a5aee">点击进入 AI 官网 </a></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325133416968.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="2_AI_47"></a>2、海康威视 AI</h5><p>海康威视必须在地址栏输入官网地址进入，否则显示403</p><p>https://open.hikvision.com</p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/201903251334410.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="3Face_AI_55"></a>3、Face++ AI</h5><p><a href="https://www.faceplusplus.com.cn" rel="nofollow" data-token="7699092b4c4fdcad69c8b058aa062329">点击进入 AI 官网 </a><br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325133726628.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="4_AI_58"></a>4、小米小爱 AI</h5><p><a href="https://xiaoai.mi.com" rel="nofollow" data-token="598905ccc00fbd8a4a07fde69f0f158d">点击进入 AI 官网 </a><br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/2019032513375549.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="5_AI_61"></a>5、搜狗 AI</h5><p><a href="http://ai.sogou.com" rel="nofollow" data-token="55d144614d6b0d89a4ecdcfdb72e4a15">点击进入 AI 官网 </a><br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325133828102.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="6OLAMI__AI_64"></a>6、OLAMI 欧拉密 AI</h5><p><a href="https://cn.olami.ai/open/website/home/home_show" rel="nofollow" data-token="59c8d83e2ff7d57e5fca4a9e29963e1a">点击进入 AI 官网 </a></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325133902529.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h5><a id="7_AI_68"></a>7、讯飞 AI</h5><p><a href="https://www.xfyun.cn" rel="nofollow" data-token="20192e7bdbb2213722640d40213d42ef">点击进入 AI 官网 </a></p><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190325133934486.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MDcxMjYz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><pre><code>                                &lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> index </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>图解HTTP</title>
      <link href="unclass/picture-explain-http/"/>
      <url>unclass/picture-explain-http/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「极客学伟」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。<br>原文链接：<a href="https://blog.csdn.net/qxuewei/article/details/100108137">https://blog.csdn.net/qxuewei/article/details/100108137</a></p><div id="content_views" class="markdown_views prism-atom-one-dark">                    <!-- flowchart 箭头图标 勿删 -->                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                    </svg>                                            <h1><a name="t0"></a><a id="HTTP_0"></a>《图解HTTP》读书笔记</h1><h2><a name="t1"></a><a id="Web_2"></a>第一章：了解Web及网路基础</h2><h3><a name="t2"></a><a id="TCPIP_4"></a>TCP/IP协议</h3><p>把互联网想关联的协议集合起来总称为TCP/IP协议<br>TCP/IP 协议族按层次分为：应用层，传输层，网络层，数据链路层</p><h4><a id="_8"></a>应用层</h4><p>决定了向用户提供应用服务时通信的活动。<br>TCP/IP 协议族内预存了各类通用的应用服务，比如：<strong>FTP</strong> 和 <strong>DNS</strong> 服务就是其中两类<br><strong>HTTP 协议也处于该层</strong></p><h4><a id="_13"></a>传输层</h4><p>传输层对上层应用层，提供处于网络连接中的两台计算机之间的数据传输。<br>在传输层有两个性质不同的协议：<strong>TCP</strong>（Transmission Control Protocol，传输控制协议）和 <strong>UDP</strong>（User Data Protocol，用户数据报协议）</p><h4><a id="_17"></a>网路层（又名网络互联层）</h4><p>网路层用来处理网络上流动的数据包。数据包是网络传输的最小数据单位，该层规定了通过怎样的路径（所谓的传输路线）到达对方的计算机，并把数据包传送给对方。与对方计算机之间通过多台计算机或网络设备进行传输时，网络层所起的作用就是在众多的选项内选择一条传输路线。</p><h4><a id="_20"></a>链路层（又名数据链路层，网络接口层）</h4><p>用来处理连接网络的硬件部分。包括操作系统、硬件的设备驱动、NIC（Network Interface Card，网络适配器，即网卡），及光纤等物理可见部分，硬件上的范畴均在链路层的作用范围之内。</p><h3><a name="t3"></a><a id="TCPIP__23"></a>TCP/IP 通信传输流</h3><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0xNV8wOC0xMC01OS5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-15_08-10-59"></p><p>利用TCP/IP 协议族进行通信时，会通过分层顺序与对方进行通信，发送端从应用层往下走，接收端则从应用层往上走。<br>发送端在层与层之间传输数据时，没经过一层时必定会被打上一个该层所属的首部信息，反之，接收端在层与层之间传输数据时，每经过一层时会把对应的首部消去。- 这种把数据信息包装起来的做法称为封装。</p><h3><a name="t4"></a><a id="_TCP__30"></a>确保可靠性的 TCP 协议</h3><p>按层次分，TCP位于传输层，提供可靠的字节流服务（字节流：为了方便传输，将大块数据分割成以报文段为单位的数据包进行管理）。<br><strong>TCP 协议为了更容易传送大数据才把数据分割，而且 TCP 协议能够确认数据最终是否送达到对方。</strong></p><h4><a id="_34"></a>如何确保数据能到达目标？</h4><p>TCP 协议采用了三次握手策略。用TCP协议把数据包送出去以后，TCP不会对传送后的情况置之不理，它一定会向对方确认是否成功送达，握手过程使用了TCP的标志：SYN（synchronize）和 ACK（acknowledgement）。<br>发送端首先先发送一个带SYN标志的数据包给对方，接收端收到后，回传一个带有 SYN/ACK 标志的数据包以示传达确认信息，最后，发送端再回传一个带 ACK 标志的数据包，代表握手结束。若捂手过程中在某个阶段莫名中断，TCP协议会在此以相同的顺序发送相同的数据包</p><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0xNV8xMy00OS0zNC5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-15_13-49-34"></p><h3><a name="t5"></a><a id="_DNS__41"></a>负责域名解析的 DNS 服务</h3><p>DNS（Domain Name System）服务是和HTTP协议一样位于应用层的协议，它提供域名到IP地址之间的解析服务。</p><p>浏览一个网址的全过程：</p><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0xNl8wNy0wMy0yMi5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-16_07-03-22"></p><h3><a name="t6"></a><a id="URLUniform_Resource_Locator__URI_48"></a>URL（Uniform Resource Locator，统一资源定位符） 和 URI（统一资源标示符）</h3><p>URL 是访问web页面需要输入的网页地址<br>URI 是由某个协议方案表示的资源的定位标示符，协议方案是指访问资源所使用的协议类型名称</p><p>URI 用字符串标识某一互联网资源，而URL表示资源的地点（互联网上所处的位置），可见 URL 是 URI 的子集。</p><h2><a name="t7"></a><a id="HTTP_54"></a>第二章：简单的HTTP协议</h2><p>HTTP请求报文由：请求方法、请求URI、协议版本、可选的请求首部字段和内容实体 构成<br><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0xNl8wNy0yNC0yOC5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-16_07-24-28"></p><h3><a name="t8"></a><a id="HTTP__59"></a>HTTP 是一种不保存状态，即无状态协议。</h3><p>HTTP 协议自身不对请求和响应之间的通信状态进行保存。目的是为了更快的处理大量事务，确保协议的可伸缩性。<br>后来有一些场景需要保存客户端的状态，比如登录状态，于是引入了 Cookie 技术。有了 Cookie 再用HTTP协议通信，就可以管理状态了。</p><h3><a name="t9"></a><a id="HTTP_63"></a>告知服务器意图的HTTP方法</h3><ul><li>GET : 获取</li><li>POST: 传输实体主体</li><li>PUT : 传输文件</li><li>HEAD: 获得报文首部</li><li>DELETE: 删除文件</li><li>OPTIONS: 询问支持的方法</li><li>TRACE：追踪路径</li><li>CONNECT：要求用隧道协议连接代理</li></ul><h3><a name="t10"></a><a id="_73"></a>持久连接节省通信量</h3><p>HTTP 初始版本，每进行一次HTTP通信就要断开一次TCP连接，当年数据小没问题，但随着HTTP的普及，HTTP所传输的内容愈来愈多，每次请求都会造成无谓的TCP连接建立和断开，增加通信量的开销。</p><p>为解决上述TCP连接的问题，HTTP/1.1 和 一部分 HTTP/1.0 相处了持久连接的方法，特点是：只要任意一端没有明确的提出断开连接，则保持TCP连接状态。</p><h4><a id="_78"></a>管线化</h4><p>持久连接使得多数请求以管线化（pipelining）方式发送成为可能，以前发送请求后需等待并受到响应，才能发送下一个请求。管线化技术出现后，不用等待响应亦可直接发送下一个请求。这样就能做到同时并行发送多个请求。而不需要一个接一个地等待响应了。</p><h2><a name="t11"></a><a id="HTTPHTTP_81"></a>第三章：HTTP报文内的HTTP信息</h2><p>请求报文和响应报文的首部内容由以下数据组成：</p><ul><li><p>请求行<br>包含用于请求的方法，请求 URI 和 HTTP 版本</p></li><li><p>状态行<br>包含响应结果的状态码，原因短语和HTTP版本</p></li><li><p>首部字段<br>包含请求和响应的各种条件和属性的各类首部<br>一般有四种首部：通用首部，请求首部，响应首部和实体首部</p></li><li><p>其他<br>可能包含HTTP的RFC 里未定义的首部（Cookie等）</p></li></ul><h3><a name="t12"></a><a id="_97"></a>编码提升传输速率</h3><h4><a id="_99"></a>报文</h4><p>是HTTP通信中的基本单位，由8位字节流组成，通过 HTTP 通信传输</p><h4><a id="_102"></a>实体</h4><p>作为请求或响应的有效载荷数据（补充项）被传输，其内容由实体首部和实体主体组成</p><p>HTTP 报文的主体用于传输请求或响应的实体主体。通常，报文主体等于实体主体。只有当传输中进行编码操作时，实体主体的内容发生变化，才导致它和报文主体产生差异。</p><h2><a name="t13"></a><a id="HTTP_107"></a>第四章：返回结果的HTTP状态码</h2><h3><a name="t14"></a><a id="_109"></a>状态码的类别</h3><div class="table-box"><table><thead><tr><th align="center"></th><th align="center">类别</th><th align="center">原因短语</th></tr></thead><tbody><tr><td align="center">1xx</td><td align="center">Infomational（信息性状态码）</td><td align="center">接收的请求正常处理</td></tr><tr><td align="center">2xx</td><td align="center">Success（成功状态码）</td><td align="center">请求正常处理完毕</td></tr><tr><td align="center">3xx</td><td align="center">Redirection（重定向状态码）</td><td align="center">需要进行附加操作以完成请求</td></tr><tr><td align="center">4xx</td><td align="center">Client Error（客户端状态错误码）</td><td align="center">服务器无法处理请求</td></tr><tr><td align="center">5xx</td><td align="center">Server Error（服务器状态码）</td><td align="center">服务器处理请求出错</td></tr></tbody></table></div><h3><a name="t15"></a><a id="_119"></a>常见错误码</h3><h4><a id="2xx___121"></a>2xx - 成功</h4><ul><li>200 OK  ： 请求被正常处理。</li><li>204 No Content ： 请求成功但返回的响应报文中不含实体的主体部分，一般只需要从客户端往服务器发送信息，而对客户端不需要发送新信息内容的情况下使用。</li><li>206 Partial Content : 客户端进行了范围请求，服务器成功执行了这部分GET请求，响应报文中包含由 Content-Range 指定范围的实体内容</li></ul><h4><a id="3xx___126"></a>3xx - 重定向</h4><ul><li>301 Moved Permanently ： 永久性重定向，该状态码表示请求的资源已被分配了新的URI，以后应使用资源现在所指的URI。</li><li>302 Found ： 临时性重定向，表示请求的资源已被分配了新的URI，希望用户本次能使用新的URI访问</li><li>303 See Other ： 表示由于请求对应的资源存在着另一个URI，应使用GET方法定向获取请求的资源。</li><li>304 Not Modified : 表示客户端发送附带条件的请求时，服务端允许请求访问资源，但未满足条件的情况。</li><li>307 Temporary Redirect : 临时重定向</li></ul><h4><a id="4xx___133"></a>4xx - 客户端错误</h4><ul><li>400 Bad Request : 请求报文中存在语法错误，当错误发生时，需修改请求的内容后再次发送请求。</li><li>401 Unauthorized ： 表示发送的请求需要有同感HTTP认证的认证信息。</li><li>403 Forbidden ： 表明对请求资源的访问被服务器拒绝了。例如未获取到文件系统的访问权限</li><li>404 Not Found ： 表明服务器上无法找到请求的资源。</li></ul><h4><a id="5xx___139"></a>5xx - 服务器错误</h4><ul><li>500 Internal Server Error ： 服务器端在执行请求时发生了错误。</li><li>503 Service Unavailable ：表明服务器暂时处于超负载或正在进行停机去维护，现在无法处理请求。</li></ul><h2><a name="t16"></a><a id="_HTTP__Web__143"></a>第五章：与 HTTP 协作的 Web 服务器</h2><p>一台 Web 服务器可搭建多个独立域名的 Web 网站，也可作为通信路径上的中转服务器提升传输速率</p><h4><a id="_146"></a>代理</h4><p>代理是一种由转发功能的应用程序，扮演了位于服务器和客户端中间人的角色，接收由客户端发送的请求并转发给服务器，同时也接收服务器返回的响应并转发给客户端<br>分缓存代理（缓存从源服务器获取的数据）和透明代理（对请求不做任何加工）</p><h4><a id="_150"></a>网关</h4><p>网关是转发其他服务器通信数据的服务器，接收从客户端发送来的请求时，它像自己拥有资源的源服务器一样对请求进行处理。<br>工作机制和代理类似，而网关能够使通信线路上的服务器提供非HTTP协议服务。利用网关能够提高通信的安全性，因为可以在客户端与网关之间的通信线路上加密以确保连接的安全。</p><h4><a id="_154"></a>隧道</h4><p>隧道是在相隔甚远的客户端和服务器两者之间进行中转，并保持双方通信连接的应用程序。<br>可按要求建立一条与其他服务器的通信线路，届时使用 SSL 等加密手段进行通信。隧道的目的是确保客户端与服务器进行安全的通信。</p><h2><a name="t17"></a><a id="HTTP_158"></a>第六章：HTTP首部</h2><p>HTTP 协议的请求和响应报文中必含HTTP首部，首部内容为客户端和服务器分别处理请求和响应提供所需要的信息。</p><h4><a id="_161"></a>请求报文</h4><p>HTTP请求报文由：方法，URI，HTTP版本，HTTP首部字段等部分构成。</p><h4><a id="_164"></a>响应报文</h4><p>HTTP响应报文由：HTTP版本，状态码（数字和原因短语），HTTP首部字段等3部分构成。</p><h3><a name="t18"></a><a id="HTTP_167"></a>HTTP首部字段</h3><p>首部字段由首部字段名和字段值构成，中间用冒号 ：分割。<br>例如HTTP首部中以 Content-Type 这个字段来表示报文主体的对象类型。</p><h4><a id="_171"></a>通用首部字段</h4><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0xOF8xMC01My0wNy5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-18_10-53-07"></p><h4><a id="_174"></a>请求首部字段</h4><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0xOF8xMC01Ni01NC5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-18_10-56-54"></p><h4><a id="_178"></a>响应首部字段</h4><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0xOF8xMS0wNy00Ni5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-18_11-07-46"></p><h4><a id="_181"></a>实体首部字段</h4><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0xOF8xMS0wOC0yNy5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-18_11-08-27"></p><h6><a id="_HTTP__184"></a>其他首部字段： HTTP 首部字段是可以自行扩展的</h6><h2><a name="t19"></a><a id="WebHTTPS_186"></a>第七章：确保Web安全的HTTPS</h2><h3><a name="t20"></a><a id="HTTP__188"></a>HTTP 的缺点</h3><ul><li>通信使用明文（不加密），内容可能会被窃听</li><li>不验证通信方的身份，因此有可能遭遇伪装</li><li>无法证明报文的完整性，所以有可能已遭篡改</li></ul><p>####加密处理防止被窃听</p><h5><a id="_194"></a>通信的加密</h5><p>HTTP 协议中没有加密机制，但可以通过和SSL（Secure Socket Layer，安全套接层）或 TLS（Transport Layer Security，安全传输层协议）的组合使用，加密HTTP的通信内容。</p><p>用SSL建立安全通信线路之后，就可以在这条线路上进行HTTP通信的。与SSL组合使用的HTTP被称为 HTTPS（HTTP Secure，超文本传输安全协议）</p><h5><a id="_199"></a>内容的加密</h5><p>通过使用证书，以证明通信方就是意料中的服务器。</p><h3><a name="t21"></a><a id="HTTP__HTTPS_203"></a>HTTP+加密+认证+完整性保护 = HTTPS</h3><p>通常，HTTP直接和TCP通信，当使用 SSL 时，则演变成先和 SSL 通信，再由SSL 和 TCP 通信了。</p><p>SSL 是独立于HTTP的协议，所以不光是HTTP协议，其他运行在应用层的SMTP和Telnet等协议均可配合SSL协议使用。可以说 SSL 是当今世界上应用最为广泛的网络安全技术。</p><p>HTTPS 采用共享密钥加密和公开密钥加密两者并用的混合加密机制。</p><p>使用SSL速度不可避免的会变慢：1.通信慢 2.大量消耗CPU和内存等资源，导致处理速度变慢。</p><h2><a name="t22"></a><a id="_212"></a>第八章：确认访问用户身份的认证</h2><p>认证的几种常见方式：</p><ul><li>密码：只有本人才会知道的字符串信息</li><li>动态令牌：仅限本人持有的设备内显示的一次性密码</li><li>数字证书：仅限本人（终端）持有的信息</li><li>生物认证：指纹和虹膜等本人的生理信息</li><li>IC卡等：仅限本人持有的信息</li></ul><p>HTTP/1.1 使用的认证方式：</p><ol><li>BASIC认证（基本认证）</li><li>DIGEST认证（摘要认证）</li><li>SSL客户端认证</li><li>FormBase认证（基于表单认证）</li></ol><h2><a name="t23"></a><a id="HTTP_226"></a>第九章：基于HTTP的功能追加协议</h2><p>使用HTTP协议存在如下瓶颈：</p><ul><li>一条连接上只可发送一个请求</li><li>请求只能从客户端开始，客户端不可以接收除响应以外的指令</li><li>请求/响应首部未经压缩就发送。首部信息越多延迟越大</li><li>发送冗长的首部，每次互相发送相同的首部造成的浪费较多</li><li>可任意选择数据压缩格式。非强制压缩发送</li></ul><h4><a id="Ajax__234"></a>Ajax 的解决方法</h4><p>Ajax（Asynchronous JavaScript and XML, 异步JavaScript与XML技术） 是一种有效利用JavaScript 和 DOM（Document Object Model） 的操作，以达到局部Web页面替换加载的异步通信手段。由于它只更新一部分界面，响应中传输的数据量会因此而减少。</p><h4><a id="Comet__237"></a>Comet 的解决方法</h4><p>通常，服务端接收到请求，在处理完毕后就会立即返回响应，但为了实现推送功能，Comet会先将响应置于挂起状态，当服务端有内容更新时，再返回该响应。因此，服务端一旦有更新，就可以立即反馈给客户端。</p><h4><a id="SPDY__240"></a>SPDY 的目标</h4><p>SPDY 没有完全改写HTTP协议，而是再TCP/IP的应用层与传输层之间通过新加会话层的形式运作。同时，考虑到安全性问题，SDPY规定通信中使用SSL。</p><p><img src= "/img/loading.gif" data-lazy-src="https://imgconvert.csdnimg.cn/aHR0cDovL2Jsb2cuaW1hZ2Uuamt4dWV3ZWkuY29tL213ZWIvMjAxOS4wOC4yNy5YbmlwMjAxOS0wOC0yMl8wOC01NC0xNy5qcGc?x-oss-process=image/format,png" alt="Xnip2019-08-22_08-54-17"></p><p>SDPY的设计图示</p><p>使用 SDPY后，HTTP协议额外获得以下功能：</p><h5><a id="_248"></a>多路复用流</h5><p>通过单一的TCP连接，可以无限制处理多个HTTP请求。所有请求的处理都在一条TCP连接上完成，因此TCP处理效率得到提高</p><h5><a id="_251"></a>赋予请求优先级</h5><h5><a id="HTTP_252"></a>压缩HTTP首部</h5><h5><a id="_253"></a>推送功能</h5><h5><a id="_254"></a>服务器提示功能</h5><p>服务器可以主动提示客户端请求所需的资源。</p><h4><a id="WebSocket_257"></a>WebSocket</h4><p>Web 浏览器与 Web 服务器之间全双工通信标准。一旦Web服务器与客户端之间建立起 WebSocket 协议的通信连接，之后所有的通信都依赖这个专用协议进行，通信过程中可互相发送JSON，XML，HTML或图片等任意格式的数据。</p><p>WebSocket 通信的主要特点：</p><ul><li>推送功能</li><li>减少通信量</li></ul><h2><a name="t24"></a><a id="Web_264"></a>第十章：构建Web内容的技术</h2><h3><a name="t25"></a><a id="HTML_HyperText_Markup_Language_266"></a>HTML （HyperText Markup Language，超文本标记语言）。</h3><p>CSS（Cascading Style Sheets，层叠样式表），可以指定如何展现HTML内的各种元素，属于样式表标准之一。</p><h3><a name="t26"></a><a id="HTMLDynamic_HTML_269"></a>动态HTML（Dynamic HTML）</h3><p>通过调用客户端脚本语言JavaScript，实现对HTML的Web页面的动态改造。利用 DOM（Document Object Model，文档对象模型）可指定欲发生动态变化的HTML元素。</p><h3><a name="t27"></a><a id="Web_272"></a>Web应用</h3><h3><a name="t28"></a><a id="_274"></a>数据发布的格式及语言·</h3><ul><li>XML</li><li>RSS</li><li>JSON</li></ul><h2><a name="t29"></a><a id="Web_279"></a>第十一章：Web的攻击技术</h2><p>HTTP 不具备必要的安全功能</p><h4><a id="SQL_283"></a>SQL注入攻击</h4><p>对Web应用使用的数据库，通过运行非法的SQL而产生的攻击。</p><h4><a id="HTTP_286"></a>HTTP首部注入攻击</h4><p>攻击者通过在响应首部字段内插入换行，添加任意响应首部或主体的一种攻击。</p><ul><li>设置任何Cookie信息</li><li>重定向至任意URL</li><li>显示任意的主体（HTTP响应截断攻击）</li></ul><h4><a id="_293"></a>目标遍历攻击</h4><p>对本无意公开的文件目录通过非法截断其目录路径后，达成访问目的的一种攻击。</p><h4><a id="_296"></a>因设置或设计上的缺陷引发的安全漏洞</h4><h4><a id="_298"></a>密码破解</h4><p>算出密码，突破认证</p><h4><a id="DoS_301"></a>DoS攻击</h4><p>一种让运行中的服务呈停止状态的攻击。</p><ul><li>集中利用访问请求造成资源过载，资源用尽的同时，实际上服务也就呈停止状态</li><li>通过攻击安全漏洞使服务停止</li></ul><p>单纯来讲就是发生大量合法请求，服务器很难分辨何为正常请求，何为攻击请求，因此很难防止DoS攻击。<br>多态计算机发起的DoS攻击成为 DDoS攻击（Distributed Denial of Service attack）。</p><pre><code>                                &lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>可能是全网最好的MySQL重要知识点/面试题总结</title>
      <link href="database/mysql/mysql-summary/"/>
      <url>database/mysql/mysql-summary/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「SnailClimb在csdn」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。<br>原文链接：<a href="https://blog.csdn.net/qq_34337272/article/details/94201189">https://blog.csdn.net/qq_34337272/article/details/94201189</a></p><div id="content_views" class="markdown_views prism-atom-one-dark">                    <!-- flowchart 箭头图标 勿删 -->                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                    </svg>                                            <p>标题有点标题党的意思，看了文章之后希望大家不会有这个想法，绝对干货！！！这篇花文章是我花了几天时间对之前总结的MySQL知识点做了完善后的产物，这篇文章可以用来回顾MySQL基础知识以及备战MySQL常见面试问题。</p><p>文末有公众号二维码，欢迎关注获取笔主最新更新文章，并可免费获取笔主总结的《Java面试突击》以及Java工程师必备学习资源。<br></p><div class="toc"><h3><a name="t0"></a>文章目录</h3><ul><ul><li><a href="#MySQL_5" rel="nofollow" data-token="40f92f4c395320b95165ff7419966844" target="_self">什么是MySQL?</a></li><li><a href="#_9" rel="nofollow" data-token="da3976286948212b046fd1454e9505c7" target="_self">事务相关</a></li><ul><li><a href="#_11" rel="nofollow" data-token="6eedfa365683009f30709e58b02529ca" target="_self">什么是事务?</a></li><li><a href="#ACID_17" rel="nofollow" data-token="1d3b4631599c2a8d6945f9ef55ba48fc" target="_self">事物的四大特性(ACID)介绍一下?</a></li><li><a href="#_26" rel="nofollow" data-token="dd70d5fc37a7006c10eedb36c8608607" target="_self">并发事务带来哪些问题?</a></li><li><a href="#MySQL_43" rel="nofollow" data-token="c4ee63869f46dd85b8b19a58d5488f4c" target="_self">事务隔离级别有哪些?MySQL的默认隔离级别是?</a></li></ul><li><a href="#_78" rel="nofollow" data-token="e0efcb894cd0cc2a776527642e54fefe" target="_self">索引相关</a></li><ul><li><a href="#_82" rel="nofollow" data-token="4971367271f313697ecd711231f4ecce" target="_self">为什么索引能提高查询速度</a></li><li><a href="#_120" rel="nofollow" data-token="681b102127025ebe08f6f2332c464b5c" target="_self">什么是最左前缀原则？</a></li><li><a href="#_134" rel="nofollow" data-token="a2bf0951e9f32e22be131562b928c787" target="_self">注意避免冗余索引</a></li><li><a href="#Mysql_140" rel="nofollow" data-token="43fa1c9ea287fbb83c87428c2b2b997e" target="_self">Mysql如何为表字段添加索引？</a></li></ul><li><a href="#_172" rel="nofollow" data-token="56e6eee47e91124d5cef7d916eda63a9" target="_self">存储引擎</a></li><ul><ul><li><a href="#_174" rel="nofollow" data-token="c556d9ac67c1e709871aa09b74dfcb4f" target="_self">一些常用命令</a></li><li><a href="#MyISAMInnoDB_202" rel="nofollow" data-token="ffbf31d34d62d21d3d5e8f0d60f3a5d0" target="_self">MyISAM和InnoDB区别</a></li></ul></ul><li><a href="#_222" rel="nofollow" data-token="e2023e04dcfea6e6084f3a8acb489fa6" target="_self">乐观锁与悲观锁的区别</a></li><ul><li><a href="#_224" rel="nofollow" data-token="578abff404671cc2ae1580eada81d5b9" target="_self">悲观锁</a></li><li><a href="#_228" rel="nofollow" data-token="27b96ea87a0fb0428b6a3e329789dad9" target="_self">乐观锁</a></li><li><a href="#_232" rel="nofollow" data-token="758c35b5e169d54c4237cbcac8682809" target="_self">两种锁的使用场景</a></li><li><a href="#_236" rel="nofollow" data-token="e03ede430b787aa17be759734fa661ed" target="_self">乐观锁常见的两种实现方式</a></li><ul><li><a href="#1__240" rel="nofollow" data-token="79155e924b39a26e92b8ec2b6ffd3d2c" target="_self">1. 版本号机制</a></li><li><a href="#2_CAS_253" rel="nofollow" data-token="1d9e472ef7aedd4113ae3a35a15de159" target="_self">2. CAS算法</a></li></ul><li><a href="#_265" rel="nofollow" data-token="71c6dc92bcf4f9fcc038e9bd9d1e29c2" target="_self">乐观锁的缺点</a></li><ul><li><a href="#1_ABA__269" rel="nofollow" data-token="97ff6679f265f6646e7296222a0b962d" target="_self">1 ABA 问题</a></li><li><a href="#2__275" rel="nofollow" data-token="e6711d56acd4e92d45293001c577a772" target="_self">2 循环时间长开销大</a></li><li><a href="#3__279" rel="nofollow" data-token="babf0f6b1b7e38a2bd7d6bfa231ac9ed" target="_self">3 只能保证一个共享变量的原子操作</a></li></ul></ul><li><a href="#InnoDB_283" rel="nofollow" data-token="e6d68a3c95aa5f64b14044941785368a" target="_self">锁机制与InnoDB锁算法</a></li><li><a href="#_311" rel="nofollow" data-token="eb6d5e9afde70f0264abf0a9b23cd75a" target="_self">大表优化</a></li><ul><li><a href="#1__315" rel="nofollow" data-token="e5dc256deec892d343abf0e1e49adf42" target="_self">1. 限定数据的范围</a></li><li><a href="#2__319" rel="nofollow" data-token="43b1e023f7666326175aaa57b900158f" target="_self">2. 读/写分离</a></li><li><a href="#3__323" rel="nofollow" data-token="7d0ab07ace8865f32741e2614b676e12" target="_self">3. 垂直分区</a></li><li><a href="#4__333" rel="nofollow" data-token="e0b7d7e9cc38f49c5ef2b089e951c3f1" target="_self">4. 水平分区</a></li></ul><li><a href="#SQLMySQL_352" rel="nofollow" data-token="a88c6903220ee69f9988933786a53c2f" target="_self">一条SQL语句在MySQL中如何执行的</a></li><li><a href="#MySQL_356" rel="nofollow" data-token="0f0f71e71150711534b9795b5ea1ec25" target="_self">MySQL高性能优化规范建议</a></li><li><a href="#SQL_360" rel="nofollow" data-token="c429962db2751e65313bf8b5742a37c4" target="_self">一条SQL语句执行得很慢的原因有哪些？</a></li><li><a href="#_MySQL__364" rel="nofollow" data-token="71a53a90acb5d646282f24d29a509b07" target="_self">一千行 MySQL 学习笔记</a></li><li><a href="#_368" rel="nofollow" data-token="df6d4e7608e3b7e60a1b34892820d3f6" target="_self">公众号</a></li></ul></ul></div><p></p><h2><a name="t1"></a><a id="MySQL_5"></a>什么是MySQL?</h2><p>MySQL 是一种关系型数据库，在Java企业级开发中非常常用，因为 MySQL 是开源免费的，并且方便扩展。阿里巴巴数据库系统也大量用到了 MySQL，因此它的稳定性是有保障的。MySQL是开放源代码的，因此任何人都可以在 GPL(General Public License) 的许可下下载并根据个性化的需要对其进行修改。MySQL的默认端口号是<strong>3306</strong>。</p><h2><a name="t2"></a><a id="_9"></a>事务相关</h2><h3><a name="t3"></a><a id="_11"></a>什么是事务?</h3><p><strong>事务是逻辑上的一组操作，要么都执行，要么都不执行。</strong></p><p>事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元，这个转账会涉及到两个关键操作就是：将小明的余额减少1000元，将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃，导致小明余额减少而小红的余额没有增加，这样就不对了。事务就是保证这两个关键操作要么都成功，要么都要失败。</p><h3><a name="t4"></a><a id="ACID_17"></a>事物的四大特性(ACID)介绍一下?</h3><p><img src= "/img/loading.gif" data-lazy-src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/%E4%BA%8B%E5%8A%A1%E7%89%B9%E6%80%A7.png" alt="事物的特性"></p><ol><li><strong>原子性：</strong> 事务是最小的执行单位，不允许分割。事务的原子性确保动作要么全部完成，要么完全不起作用；</li><li><strong>一致性：</strong> 执行事务前后，数据保持一致，多个事务对同一个数据读取的结果是相同的；</li><li><strong>隔离性：</strong> 并发访问数据库时，一个用户的事务不被其他事务所干扰，各并发事务之间数据库是独立的；</li><li><strong>持久性：</strong> 一个事务被提交之后。它对数据库中数据的改变是持久的，即使数据库发生故障也不应该对其有任何影响。</li></ol><h3><a name="t5"></a><a id="_26"></a>并发事务带来哪些问题?</h3><p>在典型的应用程序中，多个事务并发运行，经常会操作相同的数据来完成各自的任务（多个用户对统一数据进行操作）。并发虽然是必须的，但可能会导致以下的问题。</p><ul><li><strong>脏读（Dirty read）:</strong> 当一个事务正在访问数据并且对数据进行了修改，而这种修改还没有提交到数据库中，这时另外一个事务也访问了这个数据，然后使用了这个数据。因为这个数据是还没有提交的数据，那么另外一个事务读到的这个数据是“脏数据”，依据“脏数据”所做的操作可能是不正确的。</li><li><strong>丢失修改（Lost to modify）:</strong> 指在一个事务读取一个数据时，另外一个事务也访问了该数据，那么在第一个事务中修改了这个数据后，第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失，因此称为丢失修改。  例如：事务1读取某表中的数据A=20，事务2也读取A=20，事务1修改A=A-1，事务2也修改A=A-1，最终结果A=19，事务1的修改被丢失。</li><li><strong>不可重复读（Unrepeatableread）:</strong> 指在一个事务内多次读同一数据。在这个事务还没有结束时，另一个事务也访问该数据。那么，在第一个事务中的两次读数据之间，由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况，因此称为不可重复读。</li><li><strong>幻读（Phantom read）:</strong> 幻读与不可重复读类似。它发生在一个事务（T1）读取了几行数据，接着另一个并发事务（T2）插入了一些数据时。在随后的查询中，第一个事务（T1）就会发现多了一些原本不存在的记录，就好像发生了幻觉一样，所以称为幻读。</li></ul><p><strong>不可重复度和幻读区别：</strong></p><p>不可重复读的重点是修改，幻读的重点在于新增或者删除。</p><p>例1（同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ）：事务1中的A先生读取自己的工资为     1000的操作还没完成，事务2中的B先生就修改了A的工资为2000，导        致A再读自己的工资时工资变为  2000；这就是不可重复读。</p><p>例2（同样的条件, 第1次和第2次读出来的记录数不一样 ）：假某工资单表中工资大于3000的有4人，事务1读取了所有工资大于3000的人，共查到4条记录，这时事务2 又插入了一条工资大于3000的记录，事务1再次读取时查到的记录就变为了5条，这样就导致了幻读。</p><h3><a name="t6"></a><a id="MySQL_43"></a>事务隔离级别有哪些?MySQL的默认隔离级别是?</h3><p><strong>SQL 标准定义了四个隔离级别：</strong></p><ul><li><strong>READ-UNCOMMITTED(读取未提交)：</strong> 最低的隔离级别，允许读取尚未提交的数据变更，<strong>可能会导致脏读、幻读或不可重复读</strong>。</li><li><strong>READ-COMMITTED(读取已提交)：</strong> 允许读取并发事务已经提交的数据，<strong>可以阻止脏读，但是幻读或不可重复读仍有可能发生</strong>。</li><li><strong>REPEATABLE-READ(可重复读)：</strong>  对同一字段的多次读取结果都是一致的，除非数据是被本身事务自己所修改，<strong>可以阻止脏读和不可重复读，但幻读仍有可能发生</strong>。</li><li><strong>SERIALIZABLE(可串行化)：</strong> 最高的隔离级别，完全服从ACID的隔离级别。所有的事务依次逐个执行，这样事务之间就完全不可能产生干扰，也就是说，<strong>该级别可以防止脏读、不可重复读以及幻读</strong>。</li></ul><hr><div class="table-box"><table><thead><tr><th align="center">隔离级别</th><th align="center">脏读</th><th align="center">不可重复读</th><th align="center">幻影读</th></tr></thead><tbody><tr><td align="center">READ-UNCOMMITTED</td><td align="center">√</td><td align="center">√</td><td align="center">√</td></tr><tr><td align="center">READ-COMMITTED</td><td align="center">×</td><td align="center">√</td><td align="center">√</td></tr><tr><td align="center">REPEATABLE-READ</td><td align="center">×</td><td align="center">×</td><td align="center">√</td></tr><tr><td align="center">SERIALIZABLE</td><td align="center">×</td><td align="center">×</td><td align="center">×</td></tr></tbody></table></div><p>MySQL InnoDB 存储引擎的默认支持的隔离级别是 <strong>REPEATABLE-READ（可重读）</strong>。我们可以通过<code>SELECT @@tx_isolation;</code>命令来查看</p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">mysql<span class="token operator">&gt;</span> <span class="token keyword">SELECT</span> @<span class="token variable">@tx_isolation</span><span class="token punctuation">;</span><span class="token operator">+</span><span class="token comment">-----------------+</span><span class="token operator">|</span> @<span class="token variable">@tx_isolation</span>  <span class="token operator">|</span><span class="token operator">+</span><span class="token comment">-----------------+</span><span class="token operator">|</span> <span class="token keyword">REPEATABLE</span><span class="token operator">-</span><span class="token keyword">READ</span> <span class="token operator">|</span><span class="token operator">+</span><span class="token comment">-----------------+</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><p>这里需要注意的是：与 SQL 标准不同的地方在于InnoDB 存储引擎在 **REPEATABLE-READ（可重读）<strong>事务隔离级别下使用的是Next-Key Lock 锁算法，因此可以避免幻读的产生，这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 <strong>REPEATABLE-READ（可重读）</strong> 已经可以完全保证事务的隔离性要求，即达到了 SQL标准的</strong>SERIALIZABLE(可串行化)**隔离级别。</p><p>因为隔离级别越低，事务请求的锁越少，所以大部分数据库系统的隔离级别都是<strong>READ-COMMITTED(读取提交内容):</strong>，但是你要知道的是InnoDB 存储引擎默认使用 **REPEATABLE-READ（可重读）**并不会有任何性能损失。</p><p>InnoDB 存储引擎在 <strong>分布式事务</strong> 的情况下一般会用到**SERIALIZABLE(可串行化)**隔离级别。</p><h2><a name="t7"></a><a id="_78"></a>索引相关</h2><p><img src= "/img/loading.gif" data-lazy-src="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/70973487.jpg" alt="[思维导图-索引篇]"></p><h3><a name="t8"></a><a id="_82"></a>为什么索引能提高查询速度</h3><blockquote><p>以下内容整理自： 地址： <a href="https://juejin.im/post/5b55b842f265da0f9e589e79" rel="nofollow" data-token="32914170fb1af2eb6f6fd6508c0bb699">https://juejin.im/post/5b55b842f265da0f9e589e79</a> 作者 ：Java3y</p></blockquote><p><strong>先从 MySQL 的基本存储结构说起</strong></p><p>MySQL的基本存储结构是页(记录都存在页里边)：</p><p><img src= "/img/loading.gif" data-lazy-src="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/28559421.jpg" alt="MySQL的基本存储结构是页"></p><p><img src= "/img/loading.gif" data-lazy-src="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/82053134.jpg" alt=""></p><ul><li><strong>各个数据页可以组成一个双向链表</strong></li><li><strong>每个数据页中的记录又可以组成一个单向链表</strong><ul><li>每个数据页都会为存储在它里边儿的记录生成一个页目录，在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽，然后再遍历该槽对应分组中的记录即可快速找到指定的记录</li><li>以其他列(非主键)作为搜索条件：只能从最小记录开始依次遍历单链表中的每条记录。</li></ul></li></ul><p>所以说，如果我们写select * from user where indexname = 'xxx’这样没有进行任何优化的sql语句，默认会这样做：</p><ol><li><strong>定位到记录所在的页：需要遍历双向链表，找到所在的页</strong></li><li><strong>从所在的页内中查找相应的记录：由于不是根据主键查询，只能遍历所在页的单链表了</strong></li></ol><p>很明显，在数据量很大的情况下这样查找会很慢！这样的时间复杂度为O（n）。</p><p><strong>索引做了些什么可以让我们查询加快速度呢？其实就是将无序的数据变成有序(相对)：</strong></p><p><img src= "/img/loading.gif" data-lazy-src="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/5373082.jpg" alt=""></p><p>要找到id为8的记录简要步骤：</p><p><img src= "/img/loading.gif" data-lazy-src="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/89338047.jpg" alt=""></p><p>很明显的是：没有用索引我们是需要遍历双向链表来定位对应的页，现在通过 <strong>“目录”</strong> 就可以很快地定位到对应的页上了！（二分查找，时间复杂度近似为O(logn)）</p><p>其实底层结构就是B+树，B+树作为树的一种实现，能够让我们很快地查找出对应的记录。</p><blockquote><p>以下内容整理自：《Java工程师修炼之道》</p></blockquote><h3><a name="t9"></a><a id="_120"></a>什么是最左前缀原则？</h3><p>MySQL中的索引可以以一定顺序引用多列，这种索引叫作联合索引。如User表的name和city加联合索引就是(name,city)，而最左前缀原则指的是，如果查询的时候查询条件精确匹配索引的左边连续一列或几列，则此列就可以被用到。如下：</p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">select</span> <span class="token operator">*</span> <span class="token keyword">from</span> <span class="token keyword">user</span> <span class="token keyword">where</span> name<span class="token operator">=</span>xx <span class="token operator">and</span> city<span class="token operator">=</span>xx <span class="token punctuation">;</span> ／／可以命中索引<span class="token keyword">select</span> <span class="token operator">*</span> <span class="token keyword">from</span> <span class="token keyword">user</span> <span class="token keyword">where</span> name<span class="token operator">=</span>xx <span class="token punctuation">;</span> <span class="token comment">// 可以命中索引</span><span class="token keyword">select</span> <span class="token operator">*</span> <span class="token keyword">from</span> <span class="token keyword">user</span> <span class="token keyword">where</span> city<span class="token operator">=</span>xx <span class="token punctuation">;</span> <span class="token comment">// 无法命中索引            </span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre><p>这里需要注意的是，查询的时候如果两个条件都用上了，但是顺序不同，如 <code>city= xx and name ＝xx</code>，那么现在的查询引擎会自动优化为匹配联合索引的顺序，这样是能够命中索引的。</p><p>由于最左前缀原则，在创建联合索引时，索引字段的顺序需要考虑字段值去重之后的个数，较多的放前面。ORDER BY子句也遵循此规则。</p><h3><a name="t10"></a><a id="_134"></a>注意避免冗余索引</h3><p>冗余索引指的是索引的功能相同，能够命中就肯定能命中 ，那么 就是冗余索引如（name,city ）和（name ）这两个索引就是冗余索引，能够命中后者的查询肯定是能够命中前者的 在大多数情况下，都应该尽量扩展已有的索引而不是创建新索引。</p><p>MySQLS.7 版本后，可以通过查询 sys 库的 <code>schema_redundant_indexes</code> 表来查看冗余索引</p><h3><a name="t11"></a><a id="Mysql_140"></a>Mysql如何为表字段添加索引？</h3><p>1.添加PRIMARY KEY（主键索引）</p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> <span class="token punctuation">`</span>table_name<span class="token punctuation">`</span> <span class="token keyword">ADD</span> <span class="token keyword">PRIMARY</span> <span class="token keyword">KEY</span> <span class="token punctuation">(</span> <span class="token punctuation">`</span><span class="token keyword">column</span><span class="token punctuation">`</span> <span class="token punctuation">)</span> <div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p>2.添加UNIQUE(唯一索引)</p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> <span class="token punctuation">`</span>table_name<span class="token punctuation">`</span> <span class="token keyword">ADD</span> <span class="token keyword">UNIQUE</span> <span class="token punctuation">(</span> <span class="token punctuation">`</span><span class="token keyword">column</span><span class="token punctuation">`</span> <span class="token punctuation">)</span> <div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p>3.添加INDEX(普通索引)</p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> <span class="token punctuation">`</span>table_name<span class="token punctuation">`</span> <span class="token keyword">ADD</span> <span class="token keyword">INDEX</span> index_name <span class="token punctuation">(</span> <span class="token punctuation">`</span><span class="token keyword">column</span><span class="token punctuation">`</span> <span class="token punctuation">)</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p>4.添加FULLTEXT(全文索引)</p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> <span class="token punctuation">`</span>table_name<span class="token punctuation">`</span> <span class="token keyword">ADD</span> FULLTEXT <span class="token punctuation">(</span> <span class="token punctuation">`</span><span class="token keyword">column</span><span class="token punctuation">`</span><span class="token punctuation">)</span> <div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p>5.添加多列索引</p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> <span class="token punctuation">`</span>table_name<span class="token punctuation">`</span> <span class="token keyword">ADD</span> <span class="token keyword">INDEX</span> index_name <span class="token punctuation">(</span> <span class="token punctuation">`</span>column1<span class="token punctuation">`</span><span class="token punctuation">,</span> <span class="token punctuation">`</span>column2<span class="token punctuation">`</span><span class="token punctuation">,</span> <span class="token punctuation">`</span>column3<span class="token punctuation">`</span> <span class="token punctuation">)</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h2><a name="t12"></a><a id="_172"></a>存储引擎</h2><h4><a id="_174"></a>一些常用命令</h4><p><strong>查看MySQL提供的所有存储引擎</strong></p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">mysql<span class="token operator">&gt;</span> <span class="token keyword">show</span> engines<span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p><img src= "/img/loading.gif" data-lazy-src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/mysql-engines.png" alt="查看MySQL提供的所有存储引擎"></p><p>从上图我们可以查看出 MySQL 当前默认的存储引擎是InnoDB,并且在5.7版本所有的存储引擎中只有 InnoDB 是事务性存储引擎，也就是说只有 InnoDB 支持事务。</p><p><strong>查看MySQL当前默认的存储引擎</strong></p><p>我们也可以通过下面的命令查看默认的存储引擎。</p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">mysql<span class="token operator">&gt;</span> <span class="token keyword">show</span> variables <span class="token operator">like</span> <span class="token string">'%storage_engine%'</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p><strong>查看表的存储引擎</strong></p><pre class="prettyprint"><code class="prism language-sql has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">show</span> <span class="token keyword">table</span> <span class="token keyword">status</span> <span class="token operator">like</span> <span class="token string">"table_name"</span> <span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p><img src= "/img/loading.gif" data-lazy-src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/%E6%9F%A5%E7%9C%8B%E8%A1%A8%E7%9A%84%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E.png" alt="查看表的存储引擎"></p><h4><a id="MyISAMInnoDB_202"></a>MyISAM和InnoDB区别</h4><p>MyISAM是MySQL的默认数据库引擎（5.5版之前）。虽然性能极佳，而且提供了大量的特性，包括全文索引、压缩、空间函数等，但MyISAM不支持事务和行级锁，而且最大的缺陷就是崩溃后无法安全恢复。不过，5.5版本之后，MySQL引入了InnoDB（事务性数据库引擎），MySQL 5.5版本后默认的存储引擎为InnoDB。</p><p>大多数时候我们使用的都是 InnoDB 存储引擎，但是在某些情况下使用 MyISAM 也是合适的比如读密集的情况下。（如果你不介意 MyISAM 崩溃回复问题的话）。</p><p><strong>两者的对比：</strong></p><ol><li><strong>是否支持行级锁</strong> : MyISAM 只有表级锁(table-level locking)，而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。</li><li><strong>是否支持事务和崩溃后的安全恢复： MyISAM</strong> 强调的是性能，每次查询具有原子性,其执行数度比InnoDB类型更快，但是不提供事务支持。但是<strong>InnoDB</strong> 提供事务支持事务，外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。</li><li><strong>是否支持外键：</strong> MyISAM不支持，而InnoDB支持。</li><li><strong>是否支持MVCC</strong> ：仅 InnoDB 支持。应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 <code>READ COMMITTED</code> 和 <code>REPEATABLE READ</code> 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和 悲观(pessimistic)锁来实现;各数据库中MVCC实现并不统一。推荐阅读：<a href="https://segmentfault.com/a/1190000012650596" rel="nofollow" data-token="50ce0a801445dfff3ec3a26420bffdfa">MySQL-InnoDB-MVCC多版本并发控制</a></li><li>…</li></ol><p>《MySQL高性能》上面有一句话这样写到:</p><blockquote><p>不要轻易相信“MyISAM比InnoDB快”之类的经验之谈，这个结论往往不是绝对的。在很多我们已知场景中，InnoDB的速度都可以让MyISAM望尘莫及，尤其是用到了聚簇索引，或者需要访问的数据都可以放入内存的应用。</p></blockquote><p>一般情况下我们选择 InnoDB 都是没有问题的，但是某事情况下你并不在乎可扩展能力和并发能力，也不需要事务支持，也不在乎崩溃后的安全恢复问题的话，选择MyISAM也是一个不错的选择。但是一般情况下，我们都是需要考虑到这些问题的。</p><h2><a name="t13"></a><a id="_222"></a>乐观锁与悲观锁的区别</h2><h3><a name="t14"></a><a id="_224"></a>悲观锁</h3><p>总是假设最坏的情况，每次去拿数据的时候都认为别人会修改，所以每次在拿数据的时候都会上锁，这样别人想拿这个数据就会阻塞直到它拿到锁（<strong>共享资源每次只给一个线程使用，其它线程阻塞，用完后再把资源转让给其它线程</strong>）。传统的关系型数据库里边就用到了很多这种锁机制，比如行锁，表锁等，读锁，写锁等，都是在做操作之前先上锁。Java中<code>synchronized</code>和<code>ReentrantLock</code>等独占锁就是悲观锁思想的实现。</p><h3><a name="t15"></a><a id="_228"></a>乐观锁</h3><p>总是假设最好的情况，每次去拿数据的时候都认为别人不会修改，所以不会上锁，但是在更新的时候会判断一下在此期间别人有没有去更新这个数据，可以使用版本号机制和CAS算法实现。<strong>乐观锁适用于多读的应用类型，这样可以提高吞吐量</strong>，像数据库提供的类似于<strong>write_condition机制</strong>，其实都是提供的乐观锁。在Java中<code>java.util.concurrent.atomic</code>包下面的原子变量类就是使用了乐观锁的一种实现方式<strong>CAS</strong>实现的。</p><h3><a name="t16"></a><a id="_232"></a>两种锁的使用场景</h3><p>从上面对两种锁的介绍，我们知道两种锁各有优缺点，不可认为一种好于另一种，像<strong>乐观锁适用于写比较少的情况下（多读场景）</strong>，即冲突真的很少发生的时候，这样可以省去了锁的开销，加大了系统的整个吞吐量。但如果是多写的情况，一般会经常产生冲突，这就会导致上层应用会不断的进行retry，这样反倒是降低了性能，所以<strong>一般多写的场景下用悲观锁就比较合适。</strong></p><h3><a name="t17"></a><a id="_236"></a>乐观锁常见的两种实现方式</h3><blockquote><p><strong>乐观锁一般会使用版本号机制或CAS算法实现。</strong></p></blockquote><h4><a id="1__240"></a>1. 版本号机制</h4><p>一般是在数据表中加上一个数据版本号version字段，表示数据被修改的次数，当数据被修改时，version值会加一。当线程A要更新数据值时，在读取数据的同时也会读取version值，在提交更新时，若刚才读取到的version值为当前数据库中的version值相等时才更新，否则重试更新操作，直到更新成功。</p><p><strong>举一个简单的例子：</strong> 假设数据库中帐户信息表中有一个 version 字段，当前值为 1 ；而当前帐户余额字段（ balance ）为 $100 。</p><ol><li>操作员 A 此时将其读出（ version=1 ），并从其帐户余额中扣除 $50（ $100-$50 ）。</li><li>在操作员 A 操作的过程中，操作员B 也读入此用户信息（ version=1 ），并从其帐户余额中扣除 $20 （ $100-$20 ）。</li><li>操作员 A 完成了修改工作，将数据版本号加一（ version=2 ），连同帐户扣除后余额（ balance=$50 ），提交至数据库更新，此时由于提交数据版本大于数据库记录当前版本，数据被更新，数据库记录 version 更新为 2 。</li><li>操作员 B 完成了操作，也将版本号加一（ version=2 ）试图向数据库提交数据（ balance=$80 ），但此时比对数据库记录版本时发现，操作员 B 提交的数据版本号为 2 ，数据库记录当前版本也为 2 ，不满足 “ 提交版本必须大于记录当前版本才能执行更新 “ 的乐观锁策略，因此，操作员 B 的提交被驳回。</li></ol><p>这样，就避免了操作员 B 用基于 version=1 的旧数据修改的结果覆盖操作员A 的操作结果的可能。</p><h4><a id="2_CAS_253"></a>2. CAS算法</h4><p>即<strong>compare and swap（比较与交换）</strong>，是一种有名的<strong>无锁算法</strong>。无锁编程，即不使用锁的情况下实现多线程之间的变量同步，也就是在没有线程被阻塞的情况下实现变量的同步，所以也叫非阻塞同步（Non-blocking Synchronization）。<strong>CAS算法</strong>涉及到三个操作数</p><ul><li>需要读写的内存值 V</li><li>进行比较的值 A</li><li>拟写入的新值 B</li></ul><p>当且仅当 V 的值等于 A时，CAS通过原子方式用新值B来更新V的值，否则不会执行任何操作（比较和替换是一个原子操作）。一般情况下是一个<strong>自旋操作</strong>，即<strong>不断的重试</strong>。</p><p>关于自旋锁，大家可以看一下这篇文章，非常不错：<a href="https://blog.csdn.net/qq_34337272/article/details/81252853" rel="nofollow" data-token="c9644a0b8eaa9d0e9f771488f10e5568">《 面试必备之深入理解自旋锁》</a></p><h3><a name="t18"></a><a id="_265"></a>乐观锁的缺点</h3><blockquote><p>ABA 问题是乐观锁一个常见的问题</p></blockquote><h4><a id="1_ABA__269"></a>1 ABA 问题</h4><p>如果一个变量V初次读取的时候是A值，并且在准备赋值的时候检查到它仍然是A值，那我们就能说明它的值没有被其他线程修改过了吗？很明显是不能的，因为在这段时间它的值可能被改为其他值，然后又改回A，那CAS操作就会误认为它从来没有被修改过。这个问题被称为CAS操作的 <strong>"ABA"问题。</strong></p><p>JDK 1.5 以后的 <code>AtomicStampedReference 类</code>就提供了此种能力，其中的 <code>compareAndSet 方法</code>就是首先检查当前引用是否等于预期引用，并且当前标志是否等于预期标志，如果全部相等，则以原子方式将该引用和该标志的值设置为给定的更新值。</p><h4><a id="2__275"></a>2 循环时间长开销大</h4><p><strong>自旋CAS（也就是不成功就一直循环执行直到成功）如果长时间不成功，会给CPU带来非常大的执行开销。</strong> 如果JVM能支持处理器提供的pause指令那么效率会有一定的提升，pause指令有两个作用，第一它可以延迟流水线执行指令（de-pipeline）,使CPU不会消耗过多的执行资源，延迟的时间取决于具体实现的版本，在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突（memory order violation）而引起CPU流水线被清空（CPU pipeline flush），从而提高CPU的执行效率。</p><h4><a id="3__279"></a>3 只能保证一个共享变量的原子操作</h4><p>CAS 只对单个共享变量有效，当操作涉及跨多个共享变量时 CAS 无效。但是从 JDK 1.5开始，提供了<code>AtomicReference类</code>来保证引用对象之间的原子性，你可以把多个变量放在一个对象里来进行 CAS 操作.所以我们可以使用锁或者利用<code>AtomicReference类</code>把多个共享变量合并成一个共享变量来操作。</p><h2><a name="t19"></a><a id="InnoDB_283"></a>锁机制与InnoDB锁算法</h2><p><strong>MyISAM和InnoDB存储引擎使用的锁：</strong></p><ul><li>MyISAM 采用表级锁(table-level locking)。</li><li>InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁</li></ul><p><strong>表级锁和行级锁对比：</strong></p><ul><li><strong>表级锁：</strong> Mysql中锁定 <strong>粒度最大</strong> 的一种锁，对当前操作的整张表加锁，实现简单，资源消耗也比较少，加锁快，不会出现死锁。其锁定粒度最大，触发锁冲突的概率最高，并发度最低，MyISAM和 InnoDB引擎都支持表级锁。</li><li><strong>行级锁：</strong> Mysql中锁定 <strong>粒度最小</strong> 的一种锁，只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小，并发度高，但加锁的开销也最大，加锁慢，会出现死锁。</li></ul><p>详细内容可以参考： <a href="https://blog.csdn.net/qq_34337272/article/details/80611486" rel="nofollow" data-token="a1a93671f741eb9cc824a7075cae9340">Mysql锁机制简单了解一下</a></p><p><strong>InnoDB存储引擎的锁的算法有三种：</strong></p><ul><li>Record lock：单个行记录上的锁</li><li>Gap lock：间隙锁，锁定一个范围，不包括记录本身</li><li>Next-key lock：record+gap 锁定一个范围，包含记录本身</li></ul><p><strong>相关知识点：</strong></p><ol><li>innodb对于行的查询使用next-key lock</li><li>Next-locking keying为了解决Phantom Problem幻读问题</li><li>当查询的索引含有唯一属性时，将next-key lock降级为record key</li><li>Gap锁设计的目的是为了阻止多个事务将记录插入到同一范围内，而这会导致幻读问题的产生</li><li>有两种方式显式关闭gap锁：（除了外键约束和唯一性检查外，其余情况仅使用record lock） A. 将事务隔离级别设置为RC B. 将参数innodb_locks_unsafe_for_binlog设置为1</li></ol><h2><a name="t20"></a><a id="_311"></a>大表优化</h2><p>当MySQL单表记录数过大时，数据库的CRUD性能会明显下降，一些常见的优化措施如下：</p><h3><a name="t21"></a><a id="1__315"></a>1. 限定数据的范围</h3><p>务必禁止不带任何限制数据范围条件的查询语句。比如：我们当用户在查询订单历史的时候，我们可以控制在一个月的范围内；</p><h3><a name="t22"></a><a id="2__319"></a>2. 读/写分离</h3><p>经典的数据库拆分方案，主库负责写，从库负责读；</p><h3><a name="t23"></a><a id="3__323"></a>3. 垂直分区</h3><p><strong>根据数据库里面数据表的相关性进行拆分。</strong> 例如，用户表中既有用户的登录信息又有用户的基本信息，可以将用户表拆分成两个单独的表，甚至放到单独的库做分库。</p><p><strong>简单来说垂直拆分是指数据表列的拆分，把一张列比较多的表拆分为多张表。</strong> 如下图所示，这样来说大家应该就更容易理解了。<br><img src= "/img/loading.gif" data-lazy-src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%9E%82%E7%9B%B4%E5%88%86%E5%8C%BA.png" alt="数据库垂直分区"></p><ul><li><strong>垂直拆分的优点：</strong> 可以使得列数据变小，在查询时减少读取的Block数，减少I/O次数。此外，垂直分区可以简化表的结构，易于维护。</li><li><strong>垂直拆分的缺点：</strong> 主键会出现冗余，需要管理冗余列，并会引起Join操作，可以通过在应用层进行Join来解决。此外，垂直分区会让事务变得更加复杂；</li></ul><h3><a name="t24"></a><a id="4__333"></a>4. 水平分区</h3><p><strong>保持数据表结构不变，通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中，达到了分布式的目的。 水平拆分可以支撑非常大的数据量。</strong></p><p>水平拆分是指数据表行的拆分，表的行数超过200万行时，就会变慢，这时可以把一张的表的数据拆成多张表来存放。举个例子：我们可以将用户信息表拆分成多个用户信息表，这样就可以避免单一表数据量过大对性能造成影响。</p><p><img src= "/img/loading.gif" data-lazy-src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/%E6%95%B0%E6%8D%AE%E5%BA%93%E6%B0%B4%E5%B9%B3%E6%8B%86%E5%88%86.png" alt="数据库水平拆分"></p><p>水平拆分可以支持非常大的数据量。需要注意的一点是：分表仅仅是解决了单一表数据过大的问题，但由于表的数据还是在同一台机器上，其实对于提升MySQL并发能力没有什么意义，所以 <strong>水平拆分最好分库</strong> 。</p><p>水平拆分能够 <strong>支持非常大的数据量存储，应用端改造也少</strong>，但 <strong>分片事务难以解决</strong>  ，跨节点Join性能较差，逻辑复杂。《Java工程师修炼之道》的作者推荐 <strong>尽量不要对数据进行分片，因为拆分会带来逻辑、部署、运维的各种复杂度</strong> ，一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题的。如果实在要分片，尽量选择客户端分片架构，这样可以减少一次和中间件的网络I/O。</p><p><strong>下面补充一下数据库分片的两种常见方案：</strong></p><ul><li><strong>客户端代理：</strong>  <strong>分片逻辑在应用端，封装在jar包中，通过修改或者封装JDBC层来实现。</strong> 当当网的 <strong>Sharding-JDBC</strong> 、阿里的TDDL是两种比较常用的实现。</li><li><strong>中间件代理：</strong> <strong>在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。</strong> 我们现在谈的 <strong>Mycat</strong> 、360的Atlas、网易的DDB等等都是这种架构的实现。</li></ul><p>详细内容可以参考： <a href="https://segmentfault.com/a/1190000006158186" rel="nofollow" data-token="b3c8fc3b11074e2bd3f8951e470ce231">MySQL大表优化方案</a></p><h2><a name="t25"></a><a id="SQLMySQL_352"></a>一条SQL语句在MySQL中如何执行的</h2><p><a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485097&amp;idx=1&amp;sn=84c89da477b1338bdf3e9fcd65514ac1&amp;chksm=cea24962f9d5c074d8d3ff1ab04ee8f0d6486e3d015cfd783503685986485c11738ccb542ba7&amp;token=79317275&amp;lang=zh_CN#rd" rel="nofollow" data-token="91fc57e9e13f9a665f16076402cd1988">一条SQL语句在MySQL中如何执行的</a></p><h2><a name="t26"></a><a id="MySQL_356"></a>MySQL高性能优化规范建议</h2><p><a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485117&amp;idx=1&amp;sn=92361755b7c3de488b415ec4c5f46d73&amp;chksm=cea24976f9d5c060babe50c3747616cce63df5d50947903a262704988143c2eeb4069ae45420&amp;token=79317275&amp;lang=zh_CN#rd" rel="nofollow" data-token="27894dd2b90062d7cd10e664f254967c">MySQL高性能优化规范建议</a></p><h2><a name="t27"></a><a id="SQL_360"></a>一条SQL语句执行得很慢的原因有哪些？</h2><p><a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485185&amp;idx=1&amp;sn=66ef08b4ab6af5757792223a83fc0d45&amp;chksm=cea248caf9d5c1dc72ec8a281ec16aa3ec3e8066dbb252e27362438a26c33fbe842b0e0adf47&amp;token=79317275&amp;lang=zh_CN#rd" rel="nofollow" data-token="912cb4d535c6579f100a435506c6f844">腾讯面试：一条SQL语句执行得很慢的原因有哪些？—不看后悔系列</a></p><h2><a name="t28"></a><a id="_MySQL__364"></a>一千行 MySQL 学习笔记</h2><p><a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485025&amp;idx=1&amp;sn=1f4e19fc77af28f6795feff6ce7465b9&amp;chksm=cea249aaf9d5c0bc89a421c0759d27af3f55797a5fcff0111308307eff54fc4321c45ceb97ad&amp;token=283141110&amp;lang=zh_CN#rd" rel="nofollow" data-token="10094e726d13a618aceaa58982290d92">一千行 MySQL 学习笔记</a></p><h2><a name="t29"></a><a id="_368"></a>公众号</h2><p>如果大家想要实时关注我更新的文章以及分享的干货的话，可以关注我的公众号。</p><p><strong>《Java面试突击》:</strong> 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本<a href="#%E5%85%AC%E4%BC%97%E5%8F%B7" rel="nofollow" data-token="5175ed40ae48aa3e98c4c7d55fab81a2" target="_self">公众号</a>后台回复 <strong>“Java面试突击”</strong> 即可免费领取！</p><p><strong>Java工程师必备学习资源:</strong> 一些Java工程师常用学习资源公众号后台回复关键字 <strong>“1”</strong> 即可免费无套路获取。</p><p><img src= "/img/loading.gif" data-lazy-src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/167598cd2e17b8ec.png" alt="我的公众号"></p><pre><code>                                &lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> summer </tag>
            
            <tag> database </tag>
            
            <tag> mysql </tag>
            
            <tag> index </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jQuery基础笔记和面试题</title>
      <link href="front/jquery/jquery-base-note/"/>
      <url>front/jquery/jquery-base-note/</url>
      
        <content type="html"><![CDATA[<p>版权声明：本文为CSDN博主「软件大白」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。<br>原文链接：<a href="https://blog.csdn.net/qq_43645678/article/details/93380482">https://blog.csdn.net/qq_43645678/article/details/93380482</a></p><div id="content_views" class="markdown_views prism-atom-one-dark">                    <!-- flowchart 箭头图标 勿删 -->                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>                    </svg>                                            <p></p><div class="toc"><h3><a name="t0"></a>JQuery基础笔记及面试题</h3><ul><ul><li><a href="#1_jQuery__1" rel="nofollow" data-token="1ebbe8603d9a46efc7339617a93f9cad" target="_self">1. jQuery 是什么？</a></li><li><a href="#2__jQuery_29" rel="nofollow" data-token="e26aad90c9a5607aa8a4c88888b9b941" target="_self">2. 为什么要使用 jQuery?</a></li><li><a href="#3_jQuery__89" rel="nofollow" data-token="071daa6819456b90f422ddf7f9baa219" target="_self">3. jQuery 入口函数</a></li><ul><ul><li><a href="#1_jQueryJavaScript_90" rel="nofollow" data-token="e1e3323a7d25f704a388c4ed11f1533c" target="_self">1. jQuery与JavaScript加载模式对比</a></li><li><a href="#2_jQuery__158" rel="nofollow" data-token="5121bc31f9b3c6a4563285a178041c5c" target="_self">2. jQuery 其他写法</a></li><li><a href="#3__181" rel="nofollow" data-token="b793eacbbb3601b0b0aac800740b558e" target="_self">3. 解决$符号冲突问题</a></li><ul><ul><li><a href="#1____182" rel="nofollow" data-token="3c9cacbb1f8e7b7676a59ba3a6903452" target="_self">1. 释放 $ 使用权</a></li><li><a href="#2__191" rel="nofollow" data-token="5789283ca1c6688b839283d8745b0806" target="_self">2. 自定义访问符号</a></li></ul></ul></ul></ul><li><a href="#4_jQuery__200" rel="nofollow" data-token="f144cad15780114e737c4f1d3c8867c6" target="_self">4. jQuery 核心函数</a></li><li><a href="#5_jQuery__234" rel="nofollow" data-token="d4ea691e40a000aec36ab7efdaf5e39c" target="_self">5. jQuery 对象</a></li><ul><ul><li><a href="#1_jQuery__235" rel="nofollow" data-token="c7a852dabda87687ec4e635595f1f69f" target="_self">1. jQuery 对象的本质</a></li></ul></ul><li><a href="#6_jQuery__252" rel="nofollow" data-token="3290aafb414aa2ae4f55312bc532a47e" target="_self">6. jQuery 静态方法</a></li><ul><ul><li><a href="#1__253" rel="nofollow" data-token="f5181c752e8e90535593baf5248c8370" target="_self">1. 什么是静态方法</a></li><li><a href="#2_jQueryholdReady_278" rel="nofollow" data-token="cb5a6536de60ef5d594385c0364dbc37" target="_self">2. jQuery.holdReady()</a></li><li><a href="#3_each__302" rel="nofollow" data-token="0110106f1e97cb42df56fec6fd2c8cab" target="_self">3. each 方法</a></li><li><a href="#4_map__339" rel="nofollow" data-token="de127b5baec2634edb85b40a4565e524" target="_self">4. map 方法</a></li><li><a href="#5_trim__390" rel="nofollow" data-token="9017a2128cd776cde050739f792387f6" target="_self">5. trim 方法</a></li><li><a href="#6_isWindow__405" rel="nofollow" data-token="8db7baec5cb43e7ccdd8928e10d5e77f" target="_self">6. isWindow 方法</a></li><li><a href="#7_isArray__424" rel="nofollow" data-token="66ca9f6d3ebbcffb2f7914776ce8ac61" target="_self">7. isArray 方法</a></li><li><a href="#8_isFunction__440" rel="nofollow" data-token="8603d213253b09b1acd0ba9004e00899" target="_self">8. isFunction 方法</a></li></ul></ul><li><a href="#7_jQuery__463" rel="nofollow" data-token="a36b8ac7bb6beb1a9fe7d371adc35b40" target="_self">7. jQuery 选择器</a></li><ul><ul><li><a href="#1__464" rel="nofollow" data-token="5816df16573fc0cc123460c0e1b625e3" target="_self">1. 基础选择器</a></li><li><a href="#2__473" rel="nofollow" data-token="7e9d299bf8a1a4cc39def64a3948e643" target="_self">2. 层次选择器</a></li><li><a href="#3__481" rel="nofollow" data-token="6f96dd276abb46ee6fd335d078d679b3" target="_self">3. 内容过滤选择器</a></li><ul><ul><li><a href="#1_empty_489" rel="nofollow" data-token="12020e6caf984b1172409d86bcf54c97" target="_self">1. :empty</a></li><li><a href="#2_parent_520" rel="nofollow" data-token="9b8e87f27ca4c6cd93ba8b17325880ee" target="_self">2. :parent</a></li><li><a href="#3_containstext_551" rel="nofollow" data-token="232673dc5264e1b55ef80f7a2bbbb6a5" target="_self">3. :contains(text)</a></li><li><a href="#4_hasselector_583" rel="nofollow" data-token="270e23d01ae31692280c2b0a946ebbca" target="_self">4. :has(selector)</a></li></ul></ul></ul></ul><li><a href="#8_jQuery__620" rel="nofollow" data-token="b53fc50fcc26a89c93dbfb9a4168f9a6" target="_self">8. jQuery 属性操作</a></li><ul><ul><li><a href="#1__621" rel="nofollow" data-token="526f2cfdc2c55d24539cfefc4b7ee6bc" target="_self">1. 属性与属性节点</a></li><ul><ul><li><a href="#1_622" rel="nofollow" data-token="574f823ff59e166b593b766aa3f2aea3" target="_self">1.什么是属性?</a></li><li><a href="#2_626" rel="nofollow" data-token="a4869ef55a2697fe6c0e159ec37bf308" target="_self">2.如何操作属性?</a></li><li><a href="#3_634" rel="nofollow" data-token="5e1b7e5107c599cc0e424231213e0a64" target="_self">3.什么是属性节点?</a></li><li><a href="#4_642" rel="nofollow" data-token="23888c89443cc13662dce3f5744dbeed" target="_self">4.如何操作属性节点?</a></li><li><a href="#5_648" rel="nofollow" data-token="a009b64e2446e91e3b355c2e0213c1a4" target="_self">5.属性和属性节点有什么区别?</a></li></ul></ul><li><a href="#2__651" rel="nofollow" data-token="660bf590fd1eaea7fb35c66f4b076702" target="_self">2. 属性节点方法</a></li><ul><ul><li><a href="#1_attr__652" rel="nofollow" data-token="5bf91b4beb918e164a0c8efca4cde0c2" target="_self">1. attr 方法</a></li><li><a href="#2_removeAttr__680" rel="nofollow" data-token="2907add36583c982b0bccd23193792d1" target="_self">2. removeAttr 方法</a></li><li><a href="#3_prop__695" rel="nofollow" data-token="bdca49a8af58ad48d51fb44549fdbfc1" target="_self">3. prop 方法</a></li><li><a href="#4_removeProp__712" rel="nofollow" data-token="810bc8409aba847d2d77c5e3d0a6aba4" target="_self">4. removeProp 方法</a></li><li><a href="#5_attrprop_721" rel="nofollow" data-token="5daaa265654f47026733a029dadae1dd" target="_self">5. attr方法和prop方法区别</a></li></ul></ul></ul></ul><li><a href="#9_jQuery_Class__746" rel="nofollow" data-token="8a71f8032e43a79df94835138353253f" target="_self">9. jQuery Class 操作</a></li><ul><ul><li><a href="#1_jQuery_Class__747" rel="nofollow" data-token="59d04d840791757ece263f89b91c28d7" target="_self">1. jQuery Class 类操作</a></li><ul><ul><li><a href="#1_addClass_749" rel="nofollow" data-token="60dcee4557dad7186f5ca67df41ea2a8" target="_self">1. addClass</a></li><li><a href="#2_removeClass_766" rel="nofollow" data-token="ac883f9d0bec1c4d6e3a258324b2df42" target="_self">2. removeClass</a></li><li><a href="#3_toggleClass_784" rel="nofollow" data-token="7cd7b3fc45fcbace6811cc5c45c9952d" target="_self">3. toggleClass</a></li></ul></ul><li><a href="#2_jQuery__800" rel="nofollow" data-token="e00f707aedd087a80d8c56f524002733" target="_self">2. jQuery 文本值操作</a></li><ul><ul><li><a href="#1_html_801" rel="nofollow" data-token="e457f5fdfd946675ec729478472e2ca7" target="_self">1. html</a></li><li><a href="#2_text_836" rel="nofollow" data-token="70094919fd88b00be1e10ee48bac437e" target="_self">2. text</a></li><li><a href="#3_val_854" rel="nofollow" data-token="2e98d41daf76dc965a1770de5f76246c" target="_self">3. val</a></li></ul></ul><li><a href="#3_jQuery_CSS__871" rel="nofollow" data-token="8a3d95384c82efa0d803078feace94b0" target="_self">3. jQuery CSS 样式</a></li><ul><ul><li><a href="#1_css__872" rel="nofollow" data-token="ae9c6f4809376ebc02974a8785251647" target="_self">1. css 方法</a></li><li><a href="#2_width__901" rel="nofollow" data-token="c336fe6be98ca1da756bf6a920dacb31" target="_self">2. width 方法</a></li><li><a href="#3_height__917" rel="nofollow" data-token="6e5ee1bd8d3176bbd367f201d5e4bc7f" target="_self">3. height 方法</a></li></ul></ul><li><a href="#4_jQuery__934" rel="nofollow" data-token="5e87cf91efd006dcfca5d60a9c2f74c5" target="_self">4. jQuery 元素位置</a></li><ul><ul><li><a href="#1_offset__935" rel="nofollow" data-token="0cf8b403aa57461d714276f1e5172d16" target="_self">1. offset 方法</a></li><li><a href="#2_position__951" rel="nofollow" data-token="a201e64460fa74470c2a56ea5173a731" target="_self">2. position 方法</a></li></ul></ul><li><a href="#5_jQuery_scroll__968" rel="nofollow" data-token="83fa3a4c66946feda2f6b40281d95041" target="_self">5. jQuery scroll 方法</a></li><ul><ul><li><a href="#1_scrollTop__969" rel="nofollow" data-token="94a99ae0600fec17a0b133558d9381b4" target="_self">1. scrollTop 方法</a></li><li><a href="#2_scrollLeft__991" rel="nofollow" data-token="8283b11b09bde8aacc370555a4aed876" target="_self">2. scrollLeft 方法</a></li></ul></ul></ul></ul><li><a href="#10_jQuery__1016" rel="nofollow" data-token="fd67d046f0d3bfaa3bdb7f567ca05fc1" target="_self">10. jQuery 事件</a></li><ul><ul><li><a href="#1__1017" rel="nofollow" data-token="b0d3378557810b43ebdccbabe3aad9d7" target="_self">1. 事件绑定</a></li><li><a href="#2__1067" rel="nofollow" data-token="90c527dbfff05907b5324165cc424834" target="_self">2. 事件解绑</a></li><li><a href="#3__1093" rel="nofollow" data-token="c3e1abdbb5bbe56315e3169c89a380e6" target="_self">3. 事件坐标</a></li><li><a href="#4__1121" rel="nofollow" data-token="6edd40d059405a281a8da3d3dd41923d" target="_self">4. 事件冒泡</a></li><ul><ul><li><a href="#1__1122" rel="nofollow" data-token="54eefda561f2515173a024538a889b88" target="_self">1. 什么是事件冒泡</a></li><li><a href="#2__1124" rel="nofollow" data-token="b93f54b94c2b7cbc5c3ff67a562a1188" target="_self">2. 阻止事件冒泡</a></li></ul></ul><li><a href="#5__1140" rel="nofollow" data-token="843d4338f24ad1d33e718e6db6b81be1" target="_self">5. 默认行为</a></li><ul><ul><li><a href="#1__1141" rel="nofollow" data-token="13a998084e0e64ce445a3dec85c32a24" target="_self">1. 什么是默认行为</a></li><li><a href="#2__1143" rel="nofollow" data-token="893e96522c5ba95cfa98b7539bec5831" target="_self">2. 阻止默认行为</a></li></ul></ul><li><a href="#6__1159" rel="nofollow" data-token="59b5d32a578fe2586b1fb83dcffb8185" target="_self">6. 自动触发事件</a></li><ul><ul><li><a href="#1__1160" rel="nofollow" data-token="cbdaffaf1426e907ca080c1d863206b1" target="_self">1. 什么是自动触发事件</a></li><li><a href="#2__1162" rel="nofollow" data-token="82a3032ca5950e32fd9c00d00c83f2fb" target="_self">2. 自动触发方式</a></li></ul></ul><li><a href="#7__1201" rel="nofollow" data-token="3aa4a7b7bc9ef88ab57680034efb3f98" target="_self">7. 自定义事件</a></li><ul><ul><li><a href="#1__1202" rel="nofollow" data-token="08e14b24298e6245a74f91309446d7db" target="_self">1. 什么是自定义事件</a></li><li><a href="#2__1204" rel="nofollow" data-token="8e16ec142fd6577594e6bef1d976878b" target="_self">2. 自定义事件的条件</a></li></ul></ul><li><a href="#8__1219" rel="nofollow" data-token="7d3f14e44f84617421cb63f52404623c" target="_self">8. 事件命名空间</a></li><ul><ul><li><a href="#1__1220" rel="nofollow" data-token="8b417a3d92ff9429a2de7a53d717031e" target="_self">1. 什么是事件命名空间</a></li><li><a href="#2__1223" rel="nofollow" data-token="001f54d4ad86eedbba4eebf2088865b9" target="_self">2. 添加事件命名空间的条件</a></li><li><a href="#3__1226" rel="nofollow" data-token="d3dc7bc40f126d8a08ebbc9fc556e96e" target="_self">3. 事件命名空间注意点（面试题）</a></li></ul></ul><li><a href="#9__1263" rel="nofollow" data-token="dd8c999c9278987e10290982577c0447" target="_self">9. 事件委托</a></li><ul><ul><li><a href="#1__1264" rel="nofollow" data-token="dcb46830fadd2f976874394154ab599c" target="_self">1. 什么是事件委托</a></li><li><a href="#2__1268" rel="nofollow" data-token="89ff3a2fb4e35a3011d60e34e336d16f" target="_self">2. 事件委托的好处</a></li><li><a href="#3_jQuery__1275" rel="nofollow" data-token="ce1b80a2a89664930f2e8b090ee7430b" target="_self">3. jQuery 中添加事件委托</a></li></ul></ul><li><a href="#10__1342" rel="nofollow" data-token="e0396377b38cd0b16224d2bb0e6db32a" target="_self">10. 移入移出事件</a></li><ul><ul><li><a href="#1_mouseentermouseleave_1343" rel="nofollow" data-token="87cda0bcacd92fb03e64f59e7535cce0" target="_self">1. mouseenter/mouseleave</a></li><li><a href="#2_mouseovermouseout_1361" rel="nofollow" data-token="fac86912cfa9a9953661fc607fd3e922" target="_self">2. mouseover/mouseout</a></li><li><a href="#3_hover_1378" rel="nofollow" data-token="afea717873a5f473242a6a15492bf4e0" target="_self">3. hover</a></li></ul></ul></ul></ul><li><a href="#11_jQuery__1400" rel="nofollow" data-token="33128d82fedcecd613fd48c256d77bfd" target="_self">11. jQuery 动画效果</a></li><ul><ul><li><a href="#1__1401" rel="nofollow" data-token="a7fa6a58e876c097af27275df87432ed" target="_self">1. 显示，隐藏动画</a></li><ul><ul><li><a href="#1_show_1402" rel="nofollow" data-token="0c9292c529b76b26bd8d9d5598ba2402" target="_self">1. show</a></li><li><a href="#2_hide_1417" rel="nofollow" data-token="13ddff67c9893366c435625b66f84b45" target="_self">2. hide</a></li><li><a href="#3_toggle_1428" rel="nofollow" data-token="0546cd64b37b51347a63af5fdab9ce55" target="_self">3. toggle</a></li><li><a href="#4__1439" rel="nofollow" data-token="397b9542aafa36e1663e1377dceb070e" target="_self">4. 注意点</a></li></ul></ul><li><a href="#2__1448" rel="nofollow" data-token="b81eaf791e9dedfb2dfcf2895326250a" target="_self">2. 展开，收起动画</a></li><ul><ul><li><a href="#1_slideDown_1449" rel="nofollow" data-token="5f2ad4f092a7326997fd94f06096bfe2" target="_self">1. slideDown</a></li><li><a href="#2_slideUp_1458" rel="nofollow" data-token="2ee3b99665524e145484de6373fc1815" target="_self">2. slideUp</a></li><li><a href="#3_slideToggle_1467" rel="nofollow" data-token="9c90ca2a3e330c46ca204141965b0b86" target="_self">3. slideToggle</a></li></ul></ul><li><a href="#3__1477" rel="nofollow" data-token="05fb756caf8d73e7b96b0c6c4313caeb" target="_self">3. 淡入，淡出动画</a></li><ul><ul><li><a href="#1_fadeIn_1478" rel="nofollow" data-token="ae5a5366b4a5123328d323ae01e434d7" target="_self">1. fadeIn</a></li><li><a href="#2_fadeOut_1487" rel="nofollow" data-token="36fc4d36422ea767aef581aeccfb0861" target="_self">2. fadeOut</a></li><li><a href="#3_fadeToggle_1496" rel="nofollow" data-token="10a345c94eee22f91982923408438464" target="_self">3. fadeToggle</a></li><li><a href="#4_fadeTo_1505" rel="nofollow" data-token="04e6eff68196c4d3719364b4c05d1216" target="_self">4. fadeTo</a></li></ul></ul><li><a href="#4__1516" rel="nofollow" data-token="3e976b541d7ba5aad0cff6f411a4b49a" target="_self">4. 自定义动画</a></li><ul><ul><li><a href="#1_animate_1517" rel="nofollow" data-token="ae10a3fe9e873bc7b84987456b82ed86" target="_self">1. animate</a></li></ul></ul><li><a href="#5__1551" rel="nofollow" data-token="e67cf7880edccc3ffcbcbd5f7bb0a273" target="_self">5. 动画队列</a></li><li><a href="#6__1595" rel="nofollow" data-token="0429f55895c4d6bee45fc67e88afaf82" target="_self">6. 动画相关方法</a></li><ul><ul><li><a href="#1_delay_1596" rel="nofollow" data-token="b1300b99fcff243aaae76bf5b3cab97d" target="_self">1. delay</a></li><li><a href="#2_stop_1607" rel="nofollow" data-token="998b79faa19753735296e5ca0f5e4af7" target="_self">2. stop</a></li></ul></ul></ul></ul><li><a href="#12_jQuery__1627" rel="nofollow" data-token="d13dcaf1846f5523d3e1b5f0b50b3cee" target="_self">12. jQuery 文档处理</a></li><ul><ul><li><a href="#1__1628" rel="nofollow" data-token="347bcdd6996ad8c288179a76b98998c1" target="_self">1. 添加节点</a></li><ul><ul><li><a href="#1__1629" rel="nofollow" data-token="0f5f0ee85bf9d8c9595868bdd678d440" target="_self">1. 内部插入</a></li><li><a href="#2__1651" rel="nofollow" data-token="aeb109e75a85c7e4ce3c3bb612044761" target="_self">2. 外部插入</a></li></ul></ul><li><a href="#2__1673" rel="nofollow" data-token="92f9fe092fa9da4f47b18241e5b2275b" target="_self">2. 删除节点</a></li><li><a href="#3__1716" rel="nofollow" data-token="c03bf6b682a41c2135114a1cc095f70c" target="_self">3. 替换节点</a></li><li><a href="#4__1734" rel="nofollow" data-token="d5b91ae030b17068aa0d1cf2652edabd" target="_self">4. 复制节点</a></li><li><a href="#5__1760" rel="nofollow" data-token="4d2c06326247b19afd638e5abf871f72" target="_self">5. 包裹节点</a></li><li><a href="#6__1785" rel="nofollow" data-token="cab88d330ebcd89071b114363eeb9c26" target="_self">6. 遍历节点</a></li></ul></ul><li><a href="#13_jQuery__1800" rel="nofollow" data-token="cec26c0f2b9635d4b947e0c8f28f8eea" target="_self">13. jQuery 面试题</a></li><ul><ul><li><a href="#1_jQueryjquery_1801" rel="nofollow" data-token="11340e161ccadc92099217eea18c07d8" target="_self">1. 为什么要使用jQuery？jquery有哪些好处？</a></li><li><a href="#2_jQuery_1810" rel="nofollow" data-token="91cce21b57158f3fbfb1f96fd8287e6c" target="_self">2. jQuery能做什么？</a></li><li><a href="#3_jQuery____1818" rel="nofollow" data-token="37a82ffca4313d6e02903345a960460b" target="_self">3. jQuery 库中的 $() 是什么？</a></li><li><a href="#4_documentready__1823" rel="nofollow" data-token="47efba424b2c0d571b51166af3ee7b23" target="_self">4. $(document).ready() 是个什么函数？为什么要用它？</a></li><li><a href="#5_documentreadywindowonload_1828" rel="nofollow" data-token="d22075205764da2587d56ab12c7d50e2" target="_self">5. (document).ready()方法和window.onload有什么区别？</a></li><li><a href="#6_jQuerygetpost_1832" rel="nofollow" data-token="f90aad2a12a99df9ed91f69869b2ed0e" target="_self">6. jQuery中.get()提交和.post()提交的区别</a></li><li><a href="#7_jQuery_1838" rel="nofollow" data-token="4e490c5ab2cb3ee52deaaceaabee1fbe" target="_self">7. jQuery中有哪些方法可以遍历节点？</a></li><li><a href="#8_this__this__jQuery__1844" rel="nofollow" data-token="fdd14fb57ee2bfe9cc8c8e11c381aa53" target="_self">8. $(this) 和 this 关键字在 jQuery 中有何不同？</a></li><li><a href="#9__CDN__jQuery___1849" rel="nofollow" data-token="b72a21f019ed0b8c8e8c92aa2cb1917f" target="_self">9. 使用 CDN 加载 jQuery 库的主要优势是什么 ?</a></li><li><a href="#10__1854" rel="nofollow" data-token="09339dff98704d2c4d05262e4e9ac432" target="_self">10. 如何使用从服务器获取一个复杂数据(对象)?</a></li><li><a href="#11__1858" rel="nofollow" data-token="15b2d2d274822eee1b88da3998175253" target="_self">11. 在使用选择器的时要注意的地方?</a></li><li><a href="#12__1863" rel="nofollow" data-token="7b7e87c9392c323bb7c885dc27c069bc" target="_self">12. 有哪些查询节点的选择器？</a></li><li><a href="#13_jQuery____1873" rel="nofollow" data-token="54db6afb5521b94542eda8893ada1598" target="_self">13. jQuery是如何处理缓存的？ ( 要处理缓存就是禁用缓存 )</a></li><li><a href="#14_jquery_1881" rel="nofollow" data-token="5729e144d9c25cc9c7cf56a60f48b442" target="_self">14. 在jquery中你有没有编写过插件，插件有什么好处？你编写过那些插件？它应该注意那些？</a></li></ul></ul></ul></ul></div><p></p><h2><a name="t1"></a><a id="1_jQuery__1"></a>1. jQuery 是什么？</h2><p><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190823203354877.png" alt="在这里插入图片描述"></p><ul><li><p>jQuery是一款优秀的 JavaScript 库，从命名可以看出 jquery 最主要的用途是用来做查询（ jQuery = js + Query),正如 jQuery 官方 Logo 副标题所说（write less, do more)使用 jQuery 能让我们对 HTML 文档遍历和操作，事件处理，动画以及 Ajax 变得更加简单</p></li><li><p>原生 JS 设置背景</p></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">window<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>ev<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>   <span class="token comment">// 1.利用原生的JS查找DOM元素</span>   <span class="token keyword">var</span> div1 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>   <span class="token keyword">var</span> div2 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByClassName</span><span class="token punctuation">(</span><span class="token string">"box1"</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>   <span class="token keyword">var</span> div3 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"box2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><p>   <span class="token comment">// 2.利用原生的JS修改背景颜色</span><br>   div1<span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> <span class="token string">“red”</span><span class="token punctuation">;</span><br>   div2<span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> <span class="token string">“blue”</span><span class="token punctuation">;</span><br>   div3<span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> <span class="token string">“yellow”</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span></p><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li></ul></pre><ul><li>使用 jQuery 设置背景</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ready</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token comment">// 查询，操作 CSS 一步到位</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">'background'</span><span class="token punctuation">,</span><span class="token string">'red'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">'background'</span><span class="token punctuation">,</span><span class="token string">'blue'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#two"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">'background'</span><span class="token punctuation">,</span><span class="token string">'yellow'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><h2><a name="t2"></a><a id="2__jQuery_29"></a>2. 为什么要使用 jQuery?</h2><ul><li>强大的选择器：方便快速查找 DOM 元素<ul><li>通过 jQuery 查找 DOM 元素要比原生 js 快捷很多</li><li>jQuery允许开发者使用CSS1-CSS3几乎所有的选择器,以及jQuery独创的选择器</li></ul></li><li>链式调用: 可以通过 . 不断调用jQuery对象的方法<ul><li>jQuery可以通过.（点）.不断调用jQuery对象的方法，而原生JavaScript则不一定</li></ul></li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token comment">// 1.原生JavaScript</span>    <span class="token keyword">var</span> div <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token comment">// 报错,必须分开写</span>    div<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> <span class="token string">"red"</span><span class="token punctuation">.</span>width <span class="token operator">=</span> <span class="token number">200</span><span class="token operator">+</span><span class="token string">"px"</span><span class="token punctuation">;</span>    <span class="token comment">// div[0].style.width = 200+"px";</span>        <span class="token comment">// 2.jQuery</span>    <span class="token function">$</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ready</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// 不报错,后面还可以接着继续写</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">'background'</span><span class="token punctuation">,</span> <span class="token string">'yellow'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">'width'</span><span class="token punctuation">,</span> <span class="token string">'200px'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><ul><li>隐式遍历(迭代): 一次操作多个元素</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token comment">// 1.原生JavaScript</span>    <span class="token keyword">var</span> div <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token comment">// div.style.backgroundColor = "red";// 无效</span>    <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator">&lt;</span>div<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>        div<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> <span class="token string">"red"</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><pre><code>&lt;span class=&quot;token comment&quot;&gt;// 2.jQuery&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ready&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 隐式遍历(迭代)找到的所有div&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;background&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;yellow&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li></ul></pre><ul><li>读写合一: 读数据/写数据使用是一个函数</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ready</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 读取数据</span>        <span class="token keyword">var</span> $tx <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">alert</span><span class="token punctuation">(</span>$tx<span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token comment">// 写入数据</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token string">"新的数据"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre><ul><li>事件处理</li><li>DOM 操作（C增U改D删）</li><li>样式操作</li><li>动画</li><li>插件支持</li><li>浏览器兼容（建议学习1.x版本）<ul><li>1.x：兼容ie678，但相对其它版本文件较大，官方只做BUG维护，功能不再新增，最终版本：1.12.4</li><li>2.x：不兼容ie678，相对1.x文件较小，官方只做BUG维护，功能不再新增，最终版本：2.2.4</li><li>3.x：不兼容ie678，只支持最新的浏览器，很多老的jQuery插件不支持这个版本，相对1.x文件较小，提供不包含Ajax/动画API版本</li></ul></li></ul><h2><a name="t3"></a><a id="3_jQuery__89"></a>3. jQuery 入口函数</h2><h4><a id="1_jQueryJavaScript_90"></a>1. jQuery与JavaScript加载模式对比</h4><ol><li>原生JS会等到DOM元素加载完毕,并且图片也加载完毕才会执行</li><li>jQuery会等到DOM元素加载完毕,但不会等到图片也加载完毕就会执行</li></ol><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// js 原生入口函数</span>window<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>ev<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>   <span class="token comment">// 1.通过原生的JS入口函数可以拿到DOM元素</span>   <span class="token keyword">var</span> images <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">"images"</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>      <span class="token comment">// 2.通过原生的JS入口函数可以拿到DOM元素的宽高</span>   <span class="token keyword">var</span> width <span class="token operator">=</span> window<span class="token punctuation">.</span><span class="token function">getComputedStyle</span><span class="token punctuation">(</span>images<span class="token punctuation">)</span><span class="token punctuation">.</span>width<span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// jQuery 入口函数</span><span class="token function">$</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ready</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>   <span class="token comment">// 1.通过jQuery入口函数可以拿到DOM元素</span>   <span class="token keyword">var</span> $images <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"images"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><p>   <span class="token comment">// 2.通过jQuery入口函数不可以拿到DOM元素的宽高</span><br>   <span class="token keyword">var</span> $width <span class="token operator">=</span> $images<span class="token punctuation">.</span><span class="token function">width</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><p><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre><ol><li>原生的JS如果编写了多个入口函数,后面编写的会覆盖前面编写的</li><li>jQuery中编写多个入口函数,后面的不会覆盖前面的</li></ol><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 原生 js</span>window<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>ev<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"hello lnj1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 不会显示</span><span class="token punctuation">&#125;</span>window<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>ev<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"hello lnj2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 会显示</span><span class="token punctuation">&#125;</span><p><span class="token comment">// jQuery</span><br><span class="token function">$</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ready</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><br>    <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">“hello lnj1”</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 会显示</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token function">$</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ready</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><br>    <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">“hello lnj2”</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 会显示</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li></ul></pre><ul><li>jQuery 不会覆盖的本质<ul><li>jQuery框架本质是一个闭包,每次执行我们都会给ready函数传递一个新的函数,不同函数内部的数据不会相互干扰</li></ul></li><li>为何能访问$符号<ul><li>因为$符号 jQuery 框架对外暴露的一个全局变量</li></ul></li><li>为何 window.jQuery = window.$ = jQuery;   而不是window.jQuery = jQuery;<ul><li>jQuery框架不仅提供了jQuery访问还提供$访问,提升开发者的编码效率</li></ul></li><li>JavaScript中如何定义一个全局变量?<ul><li>所有全局变量是 window 对象的属性</li><li>jQuery 框架源码实现</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">window<span class="token punctuation">.</span>jQuery <span class="token operator">=</span> window<span class="token punctuation">.</span>$ <span class="token operator">=</span> jQuery<span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><ul><li>使用 jQuery 框架只有两种方式<ul><li>通过 $</li><li>通过 jQuery</li></ul></li></ul></li></ul><p><strong>总结：</strong></p><div class="table-box"><table><thead><tr><th></th><th>window.onload</th><th>$(document).ready()</th></tr></thead><tbody><tr><td>执行时机</td><td>必须等待网页全部加载完毕(包括 图片等),然后再执行包裹代码</td><td>只需要等待网页中的DOM结构 加载完毕,就能执行包裹的代码</td></tr><tr><td>执行次数</td><td>只能执行一次,如果第二次,那么 第一次的执行会被覆盖</td><td>可以执行多次,第N次都不会被上 一次覆盖</td></tr></tbody></table></div><h4><a id="2_jQuery__158"></a>2. jQuery 其他写法</h4><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"> <span class="token comment">// 1.第一种写法</span>    <span class="token function">$</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ready</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// alert("hello lnj");</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>&lt;span class=&quot;token comment&quot;&gt;// 2.第二种写法&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ready&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// alert(&quot;hello lnj&quot;);&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 3.第三种写法(推荐)&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// alert(&quot;hello lnj&quot;);&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 4.第四种写法&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello lnj&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li></ul></pre><h4><a id="3__181"></a>3. 解决$符号冲突问题</h4><h6><a id="1____182"></a>1. 释放 $ 使用权</h6><p><strong>当便捷访问符号发生冲突时,我们可以释放$使用权, 释放之后只能使用jQuery</strong></p><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">jQuery<span class="token punctuation">.</span><span class="token function">noConflict</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><p><strong>注意点:</strong></p><ul><li>释放操作必须在编写其它jQuery代码之前编写</li><li>释放之后就不能再使用$,改为使用jQuery</li></ul><h6><a id="2__191"></a>2. 自定义访问符号</h6><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"> <span class="token comment">// 2.自定义一个访问符号</span>    <span class="token keyword">var</span> nj <span class="token operator">=</span> jQuery<span class="token punctuation">.</span><span class="token function">noConflict</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">nj</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"hello lnj"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h2><a name="t4"></a><a id="4_jQuery__200"></a>4. jQuery 核心函数</h2><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//jQuery原理();就代表调用jQuery的核心函数</span><pre><code>    &lt;span class=&quot;token comment&quot;&gt;// 1.接收一个函数&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello lnj&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;// 2.接收一个字符串&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// 2.1接收一个字符串选择器&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// 返回一个jQuery对象, 对象中保存了找到的DOM元素&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $box1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.box1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $box2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#box2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;// 2.2接收一个字符串代码片段&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// 返回一个jQuery对象, 对象中保存了创建的DOM元素&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;p&amp;gt;我是段落&amp;lt;/p&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        $box1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;// 3.接收一个DOM元素&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// 会被包装成一个jQuery对象返回给我们&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; span &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;span&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $span &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;span&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;</code></pre><p><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">“</span>box1<span class="token punctuation">“</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">“</span>box2<span class="token punctuation">“</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">&gt;</span></span>我是span<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li></ul></pre><h2><a name="t5"></a><a id="5_jQuery__234"></a>5. jQuery 对象</h2><h4><a id="1_jQuery__235"></a>1. jQuery 对象的本质</h4><ul><li>jQuery 对象的本质是一个伪数组</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">var</span> $div <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$div<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><ul><li>什么是伪数组<ul><li>有 0 到 length-1 属性</li><li>并且有 length 属性<br><strong>例：</strong></li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token number">0</span><span class="token punctuation">:</span><span class="token string">"lnj"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">:</span><span class="token string">"33"</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">:</span><span class="token string">"male"</span><span class="token punctuation">,</span> length<span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">&#125;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h2><a name="t6"></a><a id="6_jQuery__252"></a>6. jQuery 静态方法</h2><h4><a id="1__253"></a>1. 什么是静态方法</h4><p><strong>静态方法对应的是对象方法,对象方法用实例对象调用,而静态方法用类名调用</strong></p><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">  <span class="token comment">// 1.定义一个类</span>  <span class="token keyword">function</span> <span class="token function">AClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>   <span class="token punctuation">&#125;</span>   <span class="token comment">// 2.给这个类添加一个静态方法</span>   <span class="token comment">// 直接添加给类的就是静态方法</span>   AClass<span class="token punctuation">.</span><span class="token function-variable function">staticMethod</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"staticMethod"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token punctuation">&#125;</span>   <span class="token comment">// 静态方法通过类名调用</span>   AClass<span class="token punctuation">.</span><span class="token function">staticMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><p>   <span class="token comment">// 3.给这个类添加一个实例方法</span><br>   AClass<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">instanceMethod</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><br>       <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">“instanceMethod”</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>   <span class="token punctuation">&#125;</span><br>   <span class="token comment">// 实例方法通过类的实例调用</span><br>   <span class="token comment">// 创建一个实例(创建一个对象)</span><br>   <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>   <span class="token comment">// 通过实例调用实例方法</span><br>   a<span class="token punctuation">.</span><span class="token function">instanceMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li></ul></pre><h4><a id="2_jQueryholdReady_278"></a>2. jQuery.holdReady()</h4><ul><li>暂停或者恢复 jQuery.ready() 事件</li><li>传入 true 或 false</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token comment">// 使用$直接调用,是静态方法</span>    $<span class="token punctuation">.</span><span class="token function">holdReady</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#first"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"我是你想要的弹窗"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>first<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>点击测试弹出<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>second<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>解除延迟<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#second"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>        $<span class="token punctuation">.</span><span class="token function">holdReady</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li></ul></pre><h4><a id="3_each__302"></a>3. each 方法</h4><ul><li>js 原生 forEach 方法<ul><li>原生的forEach方法只能遍历数组, 不能遍历伪数组</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">/*  第一个参数: 遍历到的元素  第二个参数: 当前遍历到的索引*/</span>    <span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">]</span><span class="token punctuation">;</span>    <span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token number">0</span><span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">:</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">:</span><span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">:</span><span class="token number">9</span><span class="token punctuation">,</span> length<span class="token punctuation">:</span><span class="token number">5</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>            arr<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>value<span class="token punctuation">,</span> index<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        obj<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>value<span class="token punctuation">,</span> index<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 报错</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li></ul></pre><ul><li>jQuery 的 each 静态方法<ul><li>遍历对象或数组(伪数组）</li><li>优点统一遍历对象和数组的方式</li><li>回调参数的顺序更符合我们的思维模式</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 1.利用jQuery的each静态方法遍历数组</span><span class="token comment">/*第一个参数: 当前遍历到的索引第二个参数: 遍历到的元素*/</span>    $<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>index<span class="token punctuation">,</span> value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    $<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>index<span class="token punctuation">,</span> value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li></ul></pre><h4><a id="4_map__339"></a>4. map 方法</h4><ul><li>js 原生 map 方法<ul><li>不能遍历的伪数组</li></ul></li><li>jQuery 的 map 方法<ul><li>遍历对象或数组,将回调函数的返回值组成一个新的数组返回</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>     <span class="token comment">// 4.1遍历数组</span>     <span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">]</span><span class="token punctuation">;</span>     <span class="token comment">// 4.1.1通过原生方法遍历数组</span>     <span class="token comment">// 第一个回调函数参数是遍历到的元素</span>     <span class="token comment">// 第二个回调函数参数是当前遍历的索引</span>     <span class="token comment">// 第三个回调函数参数是当前被遍历的数组</span>     <span class="token comment">// 返回值: 将回调函数返回值收集起来组成一个新的数组</span>     <span class="token keyword">var</span> res <span class="token operator">=</span> arr<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>ele<span class="token punctuation">,</span> idx<span class="token punctuation">,</span> arr<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>         console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">,</span> arr<span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token keyword">return</span> ele <span class="token operator">+</span> idx<span class="token punctuation">;</span>     <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>     console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span><span class="token punctuation">;</span>          <span class="token comment">// 4.1.2通过jQuery静态方法遍历数组</span>     <span class="token comment">// 第一个回调函数参数是遍历到的元素</span>     <span class="token comment">// 第二个回调函数参数是当前遍历的索引</span>     <span class="token comment">// 返回值: 将回调函数返回值收集起来组成一个新的数组</span>     <span class="token keyword">var</span> $res2 <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>ele<span class="token punctuation">,</span>idx<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>         console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token keyword">return</span> ele <span class="token operator">+</span> idx<span class="token punctuation">;</span>     <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>     console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res2<span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code> &lt;span class=&quot;token comment&quot;&gt;// 4.2遍历对象&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; obj &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;lnj&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; age&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;33&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gender&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;male&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* obj.map(function (ele, idx, obj) &#123;     // 报错,原生JS没有map方法     console.log(idx, ele, obj); &#125;); */&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;     console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; key &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li><li style="color: rgb(153, 153, 153);">32</li><li style="color: rgb(153, 153, 153);">33</li><li style="color: rgb(153, 153, 153);">34</li><li style="color: rgb(153, 153, 153);">35</li><li style="color: rgb(153, 153, 153);">36</li><li style="color: rgb(153, 153, 153);">37</li><li style="color: rgb(153, 153, 153);">38</li></ul></pre><ul><li>jQuery中的each静态方法和map静态方法的区别:<ol><li>each静态方法默认的返回值就是, 遍历谁就返回谁</li><li>map静态方法默认的返回值是一个空数组</li><li>each静态方法不支持在回调函数中对遍历的数组进行处理</li><li>map静态方法可以在回调函数中通过return对遍历的数组进行处理, 然后生成一个新的数组返回</li></ol></li></ul><h4><a id="5_trim__390"></a>5. trim 方法</h4><p><strong>作用:</strong> 去除字符串两端的空格<br><strong>参数:</strong> 需要去除空格的字符串<br><strong>返回值:</strong> 去除空格之后的字符串</p><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">   <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       <span class="token keyword">var</span> str <span class="token operator">=</span> <span class="token string">"   lnj   "</span><span class="token punctuation">;</span>       console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"---"</span><span class="token operator">+</span>str<span class="token operator">+</span><span class="token string">"---"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token keyword">var</span> $res <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>       console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"---"</span><span class="token operator">+</span>$res<span class="token operator">+</span><span class="token string">"---"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre><h4><a id="6_isWindow__405"></a>6. isWindow 方法</h4><p><strong>作用:</strong> 判断传入的对象是否是window对象<br><strong>返回值:</strong> true/false</p><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"> <span class="token comment">// 真数组</span>    <span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">]</span><span class="token punctuation">;</span>    <span class="token comment">// 伪数组</span>    <span class="token keyword">var</span> arrlike <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token number">0</span><span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">:</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">:</span><span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">:</span><span class="token number">9</span><span class="token punctuation">,</span> length<span class="token punctuation">:</span><span class="token number">5</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>    <span class="token comment">// 对象</span>    <span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token string">"name"</span><span class="token punctuation">:</span><span class="token string">"lnj"</span><span class="token punctuation">,</span> age<span class="token punctuation">:</span><span class="token string">"33"</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>    <span class="token comment">// 函数</span>    <span class="token keyword">var</span> <span class="token function-variable function">fn</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>    <span class="token comment">// window对象</span>    <span class="token keyword">var</span> w <span class="token operator">=</span> window<span class="token punctuation">;</span>        <span class="token keyword">var</span> res <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">isWindow</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><h4><a id="7_isArray__424"></a>7. isArray 方法</h4><p><strong>作用:</strong> 判断传入的对象是否是真数组<br><strong>返回值:</strong> true/false</p><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// 对象</span>    <span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span>name<span class="token punctuation">:</span><span class="token string">"lnj"</span><span class="token punctuation">,</span>age<span class="token punctuation">:</span> <span class="token string">"33"</span><span class="token punctuation">,</span> gender<span class="token punctuation">:</span><span class="token string">"male"</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>    <span class="token comment">// 真数组</span>    <span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">]</span><span class="token punctuation">;</span>    <span class="token keyword">var</span> $res <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// false</span>    <span class="token keyword">var</span> $res2 <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// true</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li></ul></pre><h4><a id="8_isFunction__440"></a>8. isFunction 方法</h4><p><strong>作用:</strong> 判断传入的对象是否是一个函数<br><strong>返回值:</strong> true/false<br><strong>注意点:</strong></p><ul><li>jQuery框架本质上是一个函数</li><li>(function( window, undefined ) {})( window );</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span>name<span class="token punctuation">:</span><span class="token string">"lnj"</span><span class="token punctuation">,</span>age<span class="token punctuation">:</span> <span class="token string">"33"</span><span class="token punctuation">,</span> gender<span class="token punctuation">:</span><span class="token string">"male"</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>    <span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">]</span><span class="token punctuation">;</span>    <span class="token keyword">var</span> <span class="token function-variable function">fn</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>    <span class="token keyword">var</span> $res <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">isFunction</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// false</span>    $res <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">isFunction</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">)</span><span class="token punctuation">;</span>    $res <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">isFunction</span><span class="token punctuation">(</span>fn<span class="token punctuation">)</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token comment">// 通过该方法验证了我们前面所说的,jQuery框架本质是一个匿名函数</span>    $res <span class="token operator">=</span> $<span class="token punctuation">.</span><span class="token function">isFunction</span><span class="token punctuation">(</span>$<span class="token punctuation">)</span><span class="token punctuation">;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li></ul></pre><h2><a name="t7"></a><a id="7_jQuery__463"></a>7. jQuery 选择器</h2><h4><a id="1__464"></a>1. 基础选择器</h4><div class="table-box"><table><thead><tr><th>选择器</th><th>名称</th><th>描述</th><th>返回</th><th>实例</th></tr></thead><tbody><tr><td>#id</td><td>id选择器</td><td>根据给定的id匹配一个元素</td><td>单个元素</td><td>$("#box");选取id为box元素</td></tr><tr><td>.class</td><td>类选择器</td><td>根据给定的类名匹配元素</td><td>集合元素</td><td>$(".box");选取所有类名为box元素</td></tr><tr><td>element</td><td>元素选择器</td><td>根据给定的元素名称匹配元素</td><td>集合元素</td><td>$(“p”);选取所有<p>元素</p></td></tr><tr><td>*</td><td>通配符选择器</td><td>匹配所有元素</td><td>集合元素</td><td>$("*");选取所有元素</td></tr><tr><td>selector1,selector2,selectorN</td><td>并集选择器</td><td>将所有选择器匹配到的元素合并后一起返回</td><td>集合元素</td><td>$(“div,p,.box”);选取所有<div>元素,所有<p>元素和所有类名为box元素</p></div></td></tr></tbody></table></div><h4><a id="2__473"></a>2. 层次选择器</h4><div class="table-box"><table><thead><tr><th>选择器</th><th>名称</th><th>描述</th><th>返回</th><th>实例</th></tr></thead><tbody><tr><td>$(“ancestor descendant”)</td><td>后代选择器</td><td>选取ancestor元素的所有descendant后代标签(不光是儿子,包括孙子/重孙子等)</td><td>集合元素</td><td>$(“div span”);选取<code>&lt;div&gt;</code>元素里所有的<code>&lt;span&gt;</code>元素</td></tr><tr><td>$(“parent &gt; child”)</td><td>子元素选择器</td><td>找到选取parent 元素中所有直接子元素child(只有儿子,不包括孙子/重孙子等)</td><td>集合元素</td><td>$(“div&gt;span”);选取<code>&lt;div&gt;</code>元素下元素名称是<code>&lt;span&gt;</code>的子元素</td></tr><tr><td>$(“prev + next”)</td><td>相邻兄弟选择器</td><td>选取prev元素后面紧跟的那个next元素</td><td>集合元素</td><td>$(".one+div");选取类名为one的下一个同级的<code>&lt;div&gt;</code>元素</td></tr><tr><td>$(“prev ~ siblings”)</td><td>通用兄弟选择器</td><td>选取prev元素后面的所有next元素</td><td>集合元素</td><td>$("#two~div");选取id名为two元素后面所有同级的<code>&lt;div&gt;</code>元素</td></tr></tbody></table></div><h4><a id="3__481"></a>3. 内容过滤选择器</h4><div class="table-box"><table><thead><tr><th>选择器</th><th>描述</th><th>返回</th></tr></thead><tbody><tr><td>:empty</td><td>选取不包含子元素或文本为空的元素</td><td>集合元素</td></tr><tr><td>:parent</td><td>选取含有子元素或文本的元素</td><td>集合元素</td></tr><tr><td>:contains(text)</td><td>选取含有文本内容为text的元素</td><td>集合元素</td></tr><tr><td>:has(selector)</td><td>选取含有选择器所匹配的元素的元素</td><td>集合元素</td></tr></tbody></table></div><h6><a id="1_empty_489"></a>1. :empty</h6><p><strong>作用:</strong> 找到既没有文本内容也没有子元素的指定元素</p><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token doctype">&lt;!DOCTYPE html&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>05-jQuery选择器<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>代码/js/jquery-1.12.4.js<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           <span class="token comment">// 找到所有div中不包含文本内容或子元素的元素</span>            <span class="token keyword">var</span> $res <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div:empty"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 找到1个元素</span>            $res<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>idx<span class="token punctuation">,</span>ele<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// one</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>one<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>two<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>zs<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!--包含内容不会被找到--&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>three<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!--包含子元素不会被找到--&gt;</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">&gt;</span></span>lnj<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>five<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!--不是指定元素不会被找到--&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li></ul></pre><h6><a id="2_parent_520"></a>2. :parent</h6><p><strong>作用:</strong>  找到有文本内容或有子元素的指定元素</p><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token doctype">&lt;!DOCTYPE html&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>05-jQuery选择器<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>代码/js/jquery-1.12.4.js<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           <span class="token comment">// 找到所有div中包含文本内容或子元素的元素</span>            <span class="token keyword">var</span> $res <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div:parent"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>            $res<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>one<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>two<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>zs<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!--有文本内容会被找到--&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>three<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!--有子元素会被找到--&gt;</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">&gt;</span></span>lnj<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>five<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li></ul></pre><h6><a id="3_containstext_551"></a>3. :contains(text)</h6><p><strong>作用:</strong> 找到包含指定文本内容的指定元素</p><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token doctype">&lt;!DOCTYPE html&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>05-jQuery选择器<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>代码/js/jquery-1.12.4.js<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 找到所有div中包含文本内容为lnj的元素</span>            <span class="token keyword">var</span> $res <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div:contains('lnj')"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 找到2个元素</span>            $res<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// one,three,four</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>one<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>lnj<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>two<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>zs<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>three<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>lnj<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>four<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!--子元素中包含该文本也会被找到--&gt;</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">&gt;</span></span>lnj<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>five<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li></ul></pre><h6><a id="4_hasselector_583"></a>4. :has(selector)</h6><p><strong>作用:</strong> 找到包含指定子元素的指定元素<br><strong>和:parent区别:</strong> parent只要有子元素就会被找到,:has(selector)不仅要有子元素,而且子元素还必须满足条件</p><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token doctype">&lt;!DOCTYPE html&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>05-jQuery选择器<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>代码/js/jquery-1.12.4.js<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 找到所有div中包含后代元素为span的元素</span>            <span class="token keyword">var</span> $res <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div:has('span')"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>            $res<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>idx<span class="token punctuation">,</span> ele<span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>one<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span> <span class="token comment">&lt;!--后代中包含span元素会被找到--&gt;</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">&gt;</span></span>jjj<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>two<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!--后代中不包含span元素不会被找到--&gt;</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>zs<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>three<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!--后代中包含span元素会被找到--&gt;</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">&gt;</span></span>lnj<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li></ul></pre><h2><a name="t8"></a><a id="8_jQuery__620"></a>8. jQuery 属性操作</h2><h4><a id="1__621"></a>1. 属性与属性节点</h4><h6><a id="1_622"></a>1.什么是属性?</h6><ul><li>对象身上保存的变量就是属性</li><li>只要对象身上都可以添加属性(无论是自定义对象,还是DOM对象)</li></ul><h6><a id="2_626"></a>2.如何操作属性?</h6><ul><li>添加或修改属性(没有就会添加,有就会修改)<ul><li><strong>对象.属性名称 = 值;</strong></li><li><strong>对象[“属性名称”] = 值;</strong></li></ul></li><li>获取属性<ul><li><strong>对象.属性名称;</strong></li><li><strong>对象[“属性名称”];</strong></li></ul></li></ul><h6><a id="3_634"></a>3.什么是属性节点?</h6><ul><li>在编写HTML代码时,在HTML标签中添加的属性就是属性节点</li><li>在浏览器中找到span这个DOM元素之后, 展开看到的都是属性</li><li>在attributes属性中保存的所有内容都是属性节点</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">&lt;span class= "box" nj="123"&gt;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span> // 这里的class和nj就是属性节点<div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><h6><a id="4_642"></a>4.如何操作属性节点?</h6><ul><li>获取属性节点<ul><li>DOM元素.getAttribute(“属性名称”);</li></ul></li><li>设置属性节点<ul><li>DOM元素.setAttribute(“属性名称”, “值”);</li></ul></li></ul><h6><a id="5_648"></a>5.属性和属性节点有什么区别?</h6><p><strong>任何对象都有属性, 但是只有DOM对象才有属性节点</strong></p><h4><a id="2__651"></a>2. 属性节点方法</h4><h6><a id="1_attr__652"></a>1. attr 方法</h6><p><strong>作用:</strong> 获取或者设置属性节点的值</p><ul><li>可以传递一个参数, 也可以传递两个参数</li><li>如果传递一个参数, 代表获取属性节点的值</li><li>如果传递两个参数, 代表设置属性节点的值</li></ul><p><strong>注意点:</strong></p><ul><li>如果是获取:无论找到多少个元素, 都只会返回第一个元素指定的属性节点的值</li><li>如果是设置:找到多少个元素就会设置多少个元素</li><li>如果是设置: 如果设置的属性节点不存在, 那么系统会自动新增</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">   <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       <span class="token comment">// 1.获取指定属性节点值</span>       <span class="token keyword">var</span> $res <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".span1"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string">"nj"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$res<span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token comment">// 2.设置属性节点</span>       <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".span1"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string">"nj"</span><span class="token punctuation">,</span> <span class="token string">"666"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".span2"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">,</span> <span class="token string">"box1 box2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>   &lt;span class=&quot;token comment&quot;&gt;// 3.注意点:&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// 3.1.获取属性节点时,只会获取找到所有元素中第一个元素的属性节点&lt;/span&gt;   $res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;span&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;span&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;lnj&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p>   <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li></ul></pre><h6><a id="2_removeAttr__680"></a>2. removeAttr 方法</h6><p><strong>作用:</strong> 删除属性节点</p><p><strong>注意点:</strong></p><ul><li>会删除所有找到元素指定的属性节点</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">   <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       <span class="token comment">// 1.设置属性节点时,会给所有找到元素设置属性节点</span>       <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"span"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string">"test"</span><span class="token punctuation">,</span> <span class="token string">"jonathan"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token comment">// 2.删除属性节点时,会删除所有找到元素的属性节点</span>       <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"span"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">removeAttr</span><span class="token punctuation">(</span><span class="token string">"test"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre><h6><a id="3_prop__695"></a>3. prop 方法</h6><p><strong>作用:</strong> 设置或者获取元素的属性值<br><strong>注意点:</strong></p><ul><li>prop方法不仅能够操作属性, 他还能操作属性节点</li><li>官方推荐在操作属性节点时,具有 true 和 false 两个属性的属性节点，如 checked, selected 或者 disabled 使用prop()，其他的使用 attr()</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">   <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       <span class="token comment">// 1.设置属性</span>       <span class="token comment">// 1.1.设置属性时,会设置所有找到元素的属性</span>       <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"span"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">prop</span><span class="token punctuation">(</span><span class="token string">"demo"</span><span class="token punctuation">,</span> <span class="token string">"lnj"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token comment">// 2.获取属性</span>       <span class="token comment">// 2.1.获取属性时,只会获取找到第一个元素的属性</span>       console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"span"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">prop</span><span class="token punctuation">(</span><span class="token string">"demo"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li></ul></pre><h6><a id="4_removeProp__712"></a>4. removeProp 方法</h6><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 删除所有找到元素的demo属性</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"span"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">removeProp</span><span class="token punctuation">(</span><span class="token string">"demo"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><h6><a id="5_attrprop_721"></a>5. attr方法和prop方法区别</h6><ul><li>既然所有的DOM对象，都有一个attributes属性,而prop可以操作属性,所以也可以操作属性节点</li><li>官方推荐在操作属性节点时,具有 true 和 false 两个属性的属性节点，如 checked, selected 或者 disabled 使用prop()，其他的使用 attr()</li><li>因为如果具有 true 和 false 两个属性的属性节点,如果没有编写默认attr返回undefined,而prop返回false</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">     <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>         <span class="token comment">// 1.可以通过prop获取属性节点</span>         console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"input"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">prop</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token comment">// 2.可以通过prop设置属性节点</span>         <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"input"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">prop</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"tag"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>     &lt;span class=&quot;token comment&quot;&gt;// 3.如果没有默认值,那么attr获取返回undefined&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;//console.log($(&quot;input[type=checkbox]&quot;).attr(&quot;checked&quot;));&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// 4.如果没有默认值,那么prop获取返回false&lt;/span&gt;     console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input[type=checkbox]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;checked&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// 5.通过attr设置选中&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;//$(&quot;input[type=checkbox]&quot;).attr(&quot;checked&quot;, true);&lt;/span&gt;          &lt;span class=&quot;token comment&quot;&gt;// 6.通过prop设置选中&lt;/span&gt;     &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input[type=checkbox]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;checked&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li></ul></pre><h2><a name="t9"></a><a id="9_jQuery_Class__746"></a>9. jQuery Class 操作</h2><h4><a id="1_jQuery_Class__747"></a>1. jQuery Class 类操作</h4><p><strong>jQuery CSS类相关方法都是用于操作DOM对象的class属性节点的值</strong></p><h6><a id="1_addClass_749"></a>1. addClass</h6><ul><li>给元素添加一个或多个类</li><li>如果要添加多个, 多个类名之间用空格隔开即可</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"><span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 1.添加一个类</span>        <span class="token comment">//$("div").addClass("class1");</span>        <span class="token comment">// 2.再添加一个类</span>        <span class="token comment">//$("div").addClass("class2");</span>        <span class="token comment">// 3.一次性添加多个类(用空格隔开)</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addClass</span><span class="token punctuation">(</span><span class="token string">"class1 class2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h6><a id="2_removeClass_766"></a>2. removeClass</h6><ul><li>删除元素的一个或多个类</li><li>如果想删除多个, 多个类名之间用空格隔开即可</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 4.删除一个类</span>            <span class="token comment">//$("div").removeClass("class2");</span>            <span class="token comment">// 5.再删除一个类</span>            <span class="token comment">//$("div").removeClass("class1");</span>            <span class="token comment">// 6.一次性删除多个类(用空格隔开)</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">removeClass</span><span class="token punctuation">(</span><span class="token string">"class1 class2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><h6><a id="3_toggleClass_784"></a>3. toggleClass</h6><ul><li>切换类</li><li>添加或删除一个类(存在就删除不存在就添加)</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 7.切换一个类</span>            <span class="token comment">//$("div").toggleClass("class2");</span>            <span class="token comment">// 8.切换多个类</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toggleClass</span><span class="token punctuation">(</span><span class="token string">"class1 class2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li></ul></pre><h4><a id="2_jQuery__800"></a>2. jQuery 文本值操作</h4><h6><a id="1_html_801"></a>1. html</h6><ul><li>添加或获取元素中的HTML</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token doctype">&lt;!DOCTYPE html&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>09-jQuery代码文本值<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>代码/js/jquery-1.12.4.js<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token keyword">var</span> $btns <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token keyword">var</span> $div <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            $btns<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                <span class="token comment">// 1.添加html, 相当于innerHTML</span>                <span class="token comment">//$div.html("&lt;p&gt;我是p标签&lt;/p&gt;");</span>                <span class="token comment">//$div.html("&lt;p&gt;&lt;span&gt;我是span标签&lt;/span&gt;&lt;/p&gt;");</span>                $div<span class="token punctuation">.</span><span class="token function">html</span><span class="token punctuation">(</span><span class="token string">"我是文本"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            $btns<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                <span class="token comment">// 2.获取html</span>                console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$div<span class="token punctuation">.</span><span class="token function">html</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">&gt;</span></span>添加html<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">&gt;</span></span>获取html<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">&gt;</span></span>添加文本<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">&gt;</span></span>获取文本<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li></ul></pre><h6><a id="2_text_836"></a>2. text</h6><ul><li>添加或获取元素中的文本</li><li>text方法能做的html方法都能做,所以一般使用html方法即可</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">   <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       $btns<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           <span class="token comment">// 3.添加文本, 相当于innerText</span>           <span class="token comment">// 如下内容不会被转换为标签</span>           <span class="token comment">// $div.text('&lt;p&gt;我是段落&lt;/p&gt;');</span>          $div<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token string">'我是文本'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       $btns<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           <span class="token comment">// 4.获取文本</span>           console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>$div<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><h6><a id="3_val_854"></a>3. val</h6><ul><li>添加或获取元素value属性的值</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        $btns<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 4.添加value值</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"input"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">val</span><span class="token punctuation">(</span><span class="token string">"我是一个输入框"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        $btns<span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 4.获取value值</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"input"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">val</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h4><a id="3_jQuery_CSS__871"></a>3. jQuery CSS 样式</h4><h6><a id="1_css__872"></a>1. css 方法</h6><ul><li>设置或获取元素CSS样式</li><li>格式1:DOM元素.css(“样式名称”, “值”);</li><li>格式2:DOM元素.css({“样式名称1”:“值1”,“样式名称2”:“值2”});</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">     <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>         <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 1.单个样式设置</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">"width"</span><span class="token punctuation">,</span> <span class="token string">"100px"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">"height"</span><span class="token punctuation">,</span> <span class="token string">"100px"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">"background"</span><span class="token punctuation">,</span> <span class="token string">"red"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>         &lt;span class=&quot;token comment&quot;&gt;// 2.链式设置样式&lt;/span&gt;         &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;100px&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;100px&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;background&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;red&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;// 3.传入对象一次性设置样式&lt;/span&gt;         &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;            &lt;span class=&quot;token string&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;100px&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;             &lt;span class=&quot;token string&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;100px&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;             &lt;span class=&quot;token string&quot;&gt;&quot;background&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;blue&quot;&lt;/span&gt;         &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;// 4.获取指定样式的值&lt;/span&gt;         console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li></ul></pre><h6><a id="2_width__901"></a>2. width 方法</h6><ul><li>设置或获取元素宽度(相当于获取width属性值)</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                <span class="token comment">// 1.获取元素宽度(不包括padding和border)</span>                <span class="token comment">// alert($('.son').width());</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                <span class="token comment">// 2.设置元素宽度(不包括padding和border)</span>                <span class="token comment">// $(".son").width("50px");</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h6><a id="3_height__917"></a>3. height 方法</h6><ul><li>设置或获取元素宽度(相当于获取height属性值)</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 1.获取元素宽度(不包括padding和border)</span>            <span class="token comment">// alert($('.son').width());</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 2.设置元素宽度(不包括padding和border)</span>            <span class="token comment">// $(".son").width("50px");</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h4><a id="4_jQuery__934"></a>4. jQuery 元素位置</h4><h6><a id="1_offset__935"></a>1. offset 方法</h6><ul><li>获取或设置元素相对窗口的偏移位</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 1.获取距离窗口的偏移位(从border开始)</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.son'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">offset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>left<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 100</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 2.设置距离窗口的偏移位</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.son'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">offset</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>left<span class="token punctuation">:</span><span class="token number">10</span><span class="token punctuation">,</span> top<span class="token punctuation">:</span><span class="token number">10</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h6><a id="2_position__951"></a>2. position 方法</h6><ul><li>获取相对于它最近的具有相对位置(position:relative或position:absolute)的父级元素的距离</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 1.获取匹配元素相对父元素的偏移</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.son'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">position</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>left<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 50</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 2.无效,不能设置相对定位元素的偏移位</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.son'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">position</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>left<span class="token punctuation">:</span><span class="token number">10</span><span class="token punctuation">,</span> top<span class="token punctuation">:</span><span class="token number">10</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h4><a id="5_jQuery_scroll__968"></a>5. jQuery scroll 方法</h4><h6><a id="1_scrollTop__969"></a>1. scrollTop 方法</h6><ul><li>设置或获取匹配元素相对滚动条顶部的偏移</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 7.获取匹配元素相对滚动条顶部的偏移</span>         <span class="token comment">// alert($('.scroll').scrollTop());</span>         <span class="token comment">// alert($('html').scrollTop());</span>            <span class="token comment">// 兼容所有浏览器写法</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'html'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">scrollTop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'body'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">scrollTop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 8.设置匹配元素相对滚动条顶部的偏移</span>         <span class="token comment">// $('.scroll').scrollTop(100);</span>         <span class="token comment">// $('html').scrollTop(100);</span>            <span class="token comment">// 兼容所有浏览器写法</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'html,body'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">scrollTop</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li></ul></pre><h6><a id="2_scrollLeft__991"></a>2. scrollLeft 方法</h6><ul><li>scrollLeft() 方法返回或设置匹配元素的滚动条的水平位置。</li><li>滚动条的水平位置指的是从其左侧滚动过的像素数。</li><li>当滚动条位于最左侧时，位置是 0。</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 7.获取匹配元素相对滚动条水平的偏移</span>            <span class="token comment">// alert($('.scroll').scrollLeft());</span>            <span class="token comment">// alert($('html').scrollLeft());</span>            <span class="token comment">// 兼容所有浏览器写法</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'html'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">scrollLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'body'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">scrollLeft</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 8.设置匹配元素相对滚动条水平的偏移</span>            <span class="token comment">// $('.scroll').scrollLeft(100);</span>            <span class="token comment">// $('html').scrollLeft(100);</span>            <span class="token comment">// 兼容所有浏览器写法</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'html,body'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">scrollLeft</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li></ul></pre><h2><a name="t10"></a><a id="10_jQuery__1016"></a>10. jQuery 事件</h2><h4><a id="1__1017"></a>1. 事件绑定</h4><ul><li><p>事件绑定方式一</p><ul><li>eventName(function(){})</li><li>绑定对应事件名的监听, 例如：$(’#div’).click(function(){});</li><li>优点：编码效率略高</li><li>缺点：部分事件jQuery没有实现,所以不能添加</li></ul></li><li><p>事件绑定方式二</p><ul><li>on(eventName, funcion(){})</li><li>通用的绑定事件监听, 例如：$(’#div’).on(‘click’, function(){});</li><li>优点：编码效率略低</li><li>缺点：所有js事件都可以添加</li><li>注意点：可以添加多个相同或者不同类型的事件,不会覆盖</li></ul></li></ul><p><strong>建议：</strong><br>能用eventName就用eventName, 不能用eventName就用on</p><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 1.通过eventName绑定事件</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>             <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"hello lnj"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>             <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"hello 123"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mouseleave</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>             <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"hello mouseleave"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mouseenter</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>             <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"hello mouseenter"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>    &lt;span class=&quot;token comment&quot;&gt;// 2.通过on绑定事件&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello click1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello click2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;mouseleave&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello mouseleave&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;mouseenter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello mouseenter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li></ul></pre><h4><a id="2__1067"></a>2. 事件解绑</h4><ul><li>jQuery中可以通过off(eventName,function);解绑事件</li><li>off方法如果不传递参数, 会移除所有的事件（ // $(“button”).off(); ）</li><li>off方法如果传递一个参数, 会移除所有指定类型的事件（ // $(“button”).off(“click”); ）</li><li>off方法如果传递两个参数, 会移除所有指定类型的指定事件（ $(“button”).off(“click”, test1); ）</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token keyword">function</span> <span class="token function">test1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"son1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span>        <span class="token keyword">function</span> <span class="token function">test2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"son2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span>        <span class="token keyword">function</span> <span class="token function">test3</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"son3"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".son"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span>test1<span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".son"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span>test2<span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".son"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"mouseleave"</span><span class="token punctuation">,</span> test3<span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.son&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; test1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li></ul></pre><h4><a id="3__1093"></a>3. 事件坐标</h4><ul><li><p>当事件被触发时,系统会将事件对象(event)传递给回调函数,通过event对象我们就能获取时间的坐标</p></li><li><p>获取事件坐标有三种方式</p><ul><li>event.offsetX, event.offsetY 相对于事件元素左上角</li><li>event.pageX, event.pageY  相对于页面的左上角</li><li>event.clientX, event.clientY  相对于视口的左上角</li></ul></li><li><p>event.page和event.client区别</p><ul><li>网页是可以滚动的,而视口是固定的</li><li>所以想获取距离可视区域坐标通过event.client</li><li>想获取距离网页左上角的坐标通过event.client</li></ul></li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 获取事件的坐标</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".son"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>event<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 获取相对于事件元素左上角坐标</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>event<span class="token punctuation">.</span>offsetX<span class="token punctuation">,</span> event<span class="token punctuation">.</span>offsetY<span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token comment">// 获取相对于视口左上角坐标</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>event<span class="token punctuation">.</span>clientX<span class="token punctuation">,</span> event<span class="token punctuation">.</span>clientY<span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token comment">// 获取相对于页面左上角坐标</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>event<span class="token punctuation">.</span>pageX<span class="token punctuation">,</span> event<span class="token punctuation">.</span>pageY<span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><h4><a id="4__1121"></a>4. 事件冒泡</h4><h6><a id="1__1122"></a>1. 什么是事件冒泡</h6><ul><li>事件冒泡是从目标元素逐级向上传播到根节点的过程</li></ul><h6><a id="2__1124"></a>2. 阻止事件冒泡</h6><ul><li>如果希望在触发一个元素的事件处理程序时，不影响它的父元素, 此时便可以使用停止事件冒泡</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".son"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>event<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">".son"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token comment">// 在子元素中停止事件冒泡,时间不会继续向上传播,所以父元素click方法不会被触发</span>            event<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".father"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">".father"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h4><a id="5__1140"></a>5. 默认行为</h4><h6><a id="1__1141"></a>1. 什么是默认行为</h6><ul><li>网页中的元素有自己的默认行为,例如单击超链接后会跳转,点击提交表单按钮会提交</li></ul><h6><a id="2__1143"></a>2. 阻止默认行为</h6><ul><li>可以使用event.preventDefault();方法阻止事件默认行为方法</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>event<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token keyword">var</span> str <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string">"href"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token comment">// 如果超链接是百度就不跳转</span>            <span class="token keyword">if</span><span class="token punctuation">(</span>str<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">"baidu"</span><span class="token punctuation">)</span> <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>                <span class="token comment">// 阻止默认行为</span>                event<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h4><a id="6__1159"></a>6. 自动触发事件</h4><h6><a id="1__1160"></a>1. 什么是自动触发事件</h6><ul><li>通过代码控制事件, 不用人为点击/移入/移除等事件就能被触发</li></ul><h6><a id="2__1162"></a>2. 自动触发方式</h6><ul><li>$(“selector”).trigger(“eventName”);<ul><li>触发事件的同时会触发事件冒泡</li><li>触发事件的同时会触发事件默认行为</li></ul></li><li>$(“selector”).triggerHandler(“eventName”);<ul><li>触发事件的同时不会触发事件冒泡</li><li>触发事件的同时不会触发事件默认行为</li></ul></li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">     <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>         <span class="token comment">/*         $(".son").click(function () &#123;             alert("son");         &#125;);         $(".father").click(function () &#123;             alert("father");         &#125;);<pre><code>     // trigger会触发事件冒泡     // $(&quot;.father&quot;).trigger(&quot;click&quot;);     // $(&quot;.son&quot;).trigger(&quot;click&quot;);     // triggerHandler不会触发事件冒泡     // $(&quot;.father&quot;).triggerHandler(&quot;click&quot;);     // $(&quot;.son&quot;).triggerHandler(&quot;click&quot;);     */&lt;/span&gt;     &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input[type=&#39;submit&#39;]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;         &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;点击了A标签&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// trigger会触发系统默认事件&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// $(&quot;input[type=&#39;submit&#39;]&quot;).trigger(&quot;click&quot;);&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// triggerHandler不会触发系统默认事件&lt;/span&gt;     &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input[type=&#39;submit&#39;]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;triggerHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li></ul></pre><h4><a id="7__1201"></a>7. 自定义事件</h4><h6><a id="1__1202"></a>1. 什么是自定义事件</h6><ul><li>自定义事件就是自己起一个不存在的事件名称来注册事件, 然后通过这个名称还能触发对应的方法执行, 这就是传说中的自定义事件</li></ul><h6><a id="2__1204"></a>2. 自定义事件的条件</h6><ul><li>事件必须是通过on绑定的</li><li>事件必须通过trigger来触发</li><li>因为trigger方法可以自动触发对应名称的事件,所以只要事件的名称和传递给trigger的名称一致就能执行对应的事件方法</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".father"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"njClick"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"njClick"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".father"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span><span class="token string">"njClick"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre><h4><a id="8__1219"></a>8. 事件命名空间</h4><h6><a id="1__1220"></a>1. 什么是事件命名空间</h6><ul><li>事件命名空间主要用于区分相同类型的事件,区分不同前提条件下到底应该触发哪个人编写的事件</li><li>格式: “eventName.命名空间”</li></ul><h6><a id="2__1223"></a>2. 添加事件命名空间的条件</h6><ul><li>事件是通过on来绑定的</li><li>通过trigger触发事件</li></ul><h6><a id="3__1226"></a>3. 事件命名空间注意点（面试题）</h6><ul><li>不带命名空间事件被trigger调用,会触发带命名空间事件</li><li>带命名空间事件被trigger调用,只会触发带命名空间事件</li><li>下级不带命名空间事件被trigger调用,会冒泡触发上级不带命名空间和带命名空间事件</li><li>下级带命名空间事件被trigger调用,不会触发上级不带命名空间事件</li><li>下级带命名空间事件被trigger调用,会触发上级带命名空间事件</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 给父元素添加不带命名空间事件</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".father"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"click"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"father"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token comment">// 给父元素添加带命名空间事件</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".father"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"click.66"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"66 - father"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.son&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click.nj&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;nj - 向左走&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.son&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click.66&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;66 - 向右走&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 会同时触发NJ和66编写的click事件&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 事件会冒泡到不带命名空间上级元素和带相同命名空间的上级元素&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// $(&quot;.son&quot;).trigger(&quot;click&quot;);&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 只会触发NJ编写的click事件&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 事件不会冒泡到不带命名空间上级元素&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// $(&quot;.son&quot;).trigger(&quot;click.nj&quot;);&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 只会触发66编写的click事件&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 事件只会冒泡到带相同命名空间的上级元素&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.son&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click.66&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li></ul></pre><h4><a id="9__1263"></a>9. 事件委托</h4><h6><a id="1__1264"></a>1. 什么是事件委托</h6><ul><li>事件委托就是请其他人帮忙做我们想做的事</li><li>做完之后最终的结果还是会反馈到我们这里</li></ul><h6><a id="2__1268"></a>2. 事件委托的好处</h6><ul><li>减少监听数量<ul><li>添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能，因为需要不断的与dom节点进行交互，访问dom的次数越多，引起浏览器重绘与重排的次数也就越多，就会延长整个页面的交互就绪时间</li><li>每个监听的函数都是一个对象，是对象就会占用内存，对象越多，内存占用率就越大，自然性能就越差</li></ul></li><li>新增元素自动有事件响应处理<ul><li>默认情况下新增的元素无法响应新增前添加的事件</li></ul></li></ul><h6><a id="3_jQuery__1275"></a>3. jQuery 中添加事件委托</h6><ul><li>添加前<ul><li>$(“li”).click隐式迭代给界面上所有li都添加了click事件(监听数量众多)</li><li>通过$(“ul”).append新添加的li无法影响click事件</li></ul></li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token doctype">&lt;!DOCTYPE html&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>18-jQuery事件委托<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>../day01/代码/js/jquery-1.12.4.js<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">        <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token comment">// 1.监听li点击事件</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"li"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                <span class="token comment">// 弹出当前点击行内容</span>                <span class="token function">alert</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">html</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>        &lt;span class=&quot;token comment&quot;&gt;// 2.监听新增按钮点击&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;            count&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;// 新增一行内容&lt;/span&gt;            &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ul&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;li&amp;gt;我是新增内容&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;count&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;/li&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;</code></pre><p><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span><span class="token punctuation">&gt;</span></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">&gt;</span></span>我是第1行<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">&gt;</span></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">&gt;</span></span>我是第2行<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">&gt;</span></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">&gt;</span></span>我是第3行<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">&gt;</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">&gt;</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">&gt;</span></span>新增一行<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">&gt;</span></span>移除事件委托<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li><li style="color: rgb(153, 153, 153);">32</li><li style="color: rgb(153, 153, 153);">33</li><li style="color: rgb(153, 153, 153);">34</li></ul></pre><ul><li>添加后<ul><li>格式:$(parentSelector).delegate(childrenSelector, eventName, callback)</li><li>$(“ul”).delegate隐式迭代所有ul添加事件(相比开始迭代li,必然ul的个数会少很多)</li><li>当事件被触发时,系统会自动动态查找当前是哪个li触发了事件,所以新增的li也能响应到事件</li></ul></li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">     <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>         <span class="token comment">// 1.委托ul监听li的点击事件</span>         <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"ul"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">delegate</span><span class="token punctuation">(</span><span class="token string">"li"</span><span class="token punctuation">,</span><span class="token string">"click"</span><span class="token punctuation">,</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>             <span class="token comment">// 前面我们说过事件委托就是让别人帮忙做事,但最终的结果还是会返回到我们手里,所以这里的this是触发事件的li</span>             <span class="token comment">// 这里的this之所以是触发事件的li,本质是因为"事件冒泡", 触发事件的li向上传递到ul,触发了click事件.</span>    <span class="token comment">// console.log(this);</span>             <span class="token comment">// 弹出当前点击行内容</span>             <span class="token function">alert</span><span class="token punctuation">(</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">html</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>     &lt;span class=&quot;token comment&quot;&gt;// 2.监听新增按钮点击&lt;/span&gt;     &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;         count&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;// 新增一行内容&lt;/span&gt;         &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ul&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;li&amp;gt;我是新增内容&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;count&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;/li&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li></ul></pre><h4><a id="10__1342"></a>10. 移入移出事件</h4><h6><a id="1_mouseentermouseleave_1343"></a>1. mouseenter/mouseleave</h6><ul><li>移动到子元素不会触发事件</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 移动到子元素不会触发事件</span>         <span class="token comment">// 2.1移入事件</span>         <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.father'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mouseenter</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'mouseenter'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token comment">// 2.2移除事件</span>         <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.father'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mouseleave</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'mouseleave'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><h6><a id="2_mouseovermouseout_1361"></a>2. mouseover/mouseout</h6><ul><li>移动到子元素会触发事件</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">     <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>          <span class="token comment">// 2.1移入事件</span>          <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.father'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mouseover</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'mouseover'</span><span class="token punctuation">)</span> <span class="token punctuation">;</span>          <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>          <span class="token comment">// 2.2移除事件</span>          <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.father'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mouseout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'mouseout'</span><span class="token punctuation">)</span> <span class="token punctuation">;</span>          <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>     <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre><h6><a id="3_hover_1378"></a>3. hover</h6><ul><li>内容监听移入和移出</li><li>内部实现就是调用mouseenter和mouseleave</li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">     <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>         <span class="token comment">/*        // 传入两个回调函数,一个监听移入,一个监听移出         $(".father").hover(function () &#123;             console.log("mouseenter");         &#125;, function () &#123;             console.log("mouseleave");         &#125;);         */</span>         <span class="token comment">// 如果只传入一个方式,那么这个方式既监听移入也监听移出</span>         <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".father"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">hover</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>             console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"移入移除"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>         <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>     <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li></ul></pre><h2><a name="t11"></a><a id="11_jQuery__1400"></a>11. jQuery 动画效果</h2><h4><a id="1__1401"></a>1. 显示，隐藏动画</h4><h6><a id="1_show_1402"></a>1. show</h6><ul><li>显示动画</li><li>内部实现原理根据当前操作的元素是块级还是行内决定, 块级内部调用display:block;,行内内部调用display:inline;</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 编写jQuery相关代码</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// $("div").css("display", "block");</span>    <span class="token comment">// 注意: 这里的时间是毫秒</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 作用: 动画执行完毕之后调用</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"显示动画执行完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre><h6><a id="2_hide_1417"></a>2. hide</h6><ul><li>隐藏动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// $("div").css("display", "none");</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">hide</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"隐藏动画执行完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><h6><a id="3_toggle_1428"></a>3. toggle</h6><ul><li>切换动画（显示变隐藏，隐藏变显示）</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toggle</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"切换动画执行完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h6><a id="4__1439"></a>4. 注意点</h6><ul><li>show(1000, function () {}😉 第一个参数单位是毫秒, 1000毫秒等于1秒</li><li>默认的动画时长是400毫秒</li><li>除了指定毫秒以外还可以指定三个预设参数 slow、normal、fast<ul><li>slow本质是600毫秒</li><li>normal本质是400毫秒</li><li>fast本质是200毫秒</li></ul></li><li>其它两个方法同理可证</li></ul><h4><a id="2__1448"></a>2. 展开，收起动画</h4><h6><a id="1_slideDown_1449"></a>1. slideDown</h6><ul><li>展开动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideDown</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"展开完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h6><a id="2_slideUp_1458"></a>2. slideUp</h6><ul><li>收起动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideUp</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"收起完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h6><a id="3_slideToggle_1467"></a>3. slideToggle</h6><ul><li>切换动画（ 展开变收起,收起变展开）</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideToggle</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"收起完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h4><a id="3__1477"></a>3. 淡入，淡出动画</h4><h6><a id="1_fadeIn_1478"></a>1. fadeIn</h6><ul><li>淡入动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">fadeIn</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"淡入完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h6><a id="2_fadeOut_1487"></a>2. fadeOut</h6><ul><li>淡出动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">fadeOut</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"淡出完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h6><a id="3_fadeToggle_1496"></a>3. fadeToggle</h6><ul><li>切换动画（显示变淡出，不显示变淡入）</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">fadeToggle</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"切换完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h6><a id="4_fadeTo_1505"></a>4. fadeTo</h6><ul><li>淡入到指定透明度动画</li><li>可以通过第二个参数,淡入到指定的透明度(取值范围0~1)</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">fadeTo</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token number">0.2</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"淡入完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h4><a id="4__1516"></a>4. 自定义动画</h4><h6><a id="1_animate_1517"></a>1. animate</h6><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">/*第一个参数: 接收一个对象, 可以在对象中修改属性第二个参数: 指定动画时长第三个参数: 指定动画节奏, 默认就是swing第四个参数: 动画执行完毕之后的回调函数*/</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".two"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">animate</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>    marginLeft<span class="token punctuation">:</span> <span class="token number">500</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token number">5000</span><span class="token punctuation">,</span> <span class="token string">"linear"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// alert("自定义动画执行完毕");</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li></ul></pre><ul><li>每次开始运动都必须是初始位置或者初始状态,如果想在上一次位置或者状态下再次进行动画可以使用累加动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">animate</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>        width<span class="token punctuation">:</span> <span class="token string">"+=100"</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"自定义动画执行完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre><ul><li>同时操作多个属性,自定义动画会执行同步动画,多个被操作的属性一起执行动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">animate</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>    width<span class="token punctuation">:</span> <span class="token number">500</span><span class="token punctuation">,</span>    height<span class="token punctuation">:</span> <span class="token number">500</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"自定义动画执行完毕"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><h4><a id="5__1551"></a>5. 动画队列</h4><ul><li>多个动画方法链式编程,会等到前面的动画执行完毕再依次执行后续动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideDown</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideUp</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span><p><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">“.one”</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideDown</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><br>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">“.one”</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideUp</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><br>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">“.one”</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre><ul><li>但是如果后面紧跟一个非动画方法则会被立即执行</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 立刻变为黄色,然后再执行动画</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideDown</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideUp</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">"background"</span><span class="token punctuation">,</span> <span class="token string">"yellow"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre><ul><li>如果想颜色再动画执行完毕之后设置<ul><li>1.使用回调</li><li>2.使用动画队列</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideDown</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideUp</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">"background"</span><span class="token punctuation">,</span> <span class="token string">"yellow"</span><span class="token punctuation">)</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><p><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">“.one”</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideDown</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideUp</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">queue</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><br>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">“.one”</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">“background”</span><span class="token punctuation">,</span> <span class="token string">“yellow”</span><span class="token punctuation">)</span><br><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li></ul></pre><ul><li>注意：<ul><li>动画队列方法queue()后面不能继续直接添加queue()</li><li>如果想继续添加必须在上一个queue()方法中next()方法</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideDown</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slideUp</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">queue</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>next<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">"background"</span><span class="token punctuation">,</span> <span class="token string">"yellow"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 关键点</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">queue</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">css</span><span class="token punctuation">(</span><span class="token string">"width"</span><span class="token punctuation">,</span> <span class="token string">"500px"</span><span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><h4><a id="6__1595"></a>6. 动画相关方法</h4><h6><a id="1_delay_1596"></a>1. delay</h6><ul><li>设置动画延迟时长</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".one"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">animate</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>    width<span class="token punctuation">:</span> <span class="token number">500</span>    <span class="token comment">// height: 500</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">delay</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">animate</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>    height<span class="token punctuation">:</span> <span class="token number">500</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre><h6><a id="2_stop_1607"></a>2. stop</h6><ul><li>停止指定元素上正在执行的动画</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"> <span class="token comment">// 立即停止当前动画, 继续执行后续的动画</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>&lt;span class=&quot;token comment&quot;&gt;// 立即停止当前和后续所有的动画&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 立即完成当前的, 继续执行后续动画&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 立即完成当前的, 并且停止后续所有的&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li></ul></pre><h2><a name="t12"></a><a id="12_jQuery__1627"></a>12. jQuery 文档处理</h2><h4><a id="1__1628"></a>1. 添加节点</h4><h6><a id="1__1629"></a>1. 内部插入</h6><ul><li>append</li><li>appendTo<ul><li>将元素添加到指定元素内部的最后</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 1.创建一个节点</span><span class="token keyword">var</span> $li <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"&lt;li&gt;新增的li&lt;/li&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 2.添加节点</span><span class="token comment">// $("ul").append($li);</span>$li<span class="token punctuation">.</span><span class="token function">appendTo</span><span class="token punctuation">(</span><span class="token string">"ul"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><ul><li>prepend</li><li>prependTo<ul><li>将元素添加到指定元素内部的最前面</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 1.创建一个节点</span><span class="token keyword">var</span> $li <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"&lt;li&gt;新增的li&lt;/li&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 2.添加节点</span><span class="token comment">// $("ul").prepend($li);</span>$li<span class="token punctuation">.</span><span class="token function">prependTo</span><span class="token punctuation">(</span><span class="token string">"ul"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h6><a id="2__1651"></a>2. 外部插入</h6><ul><li>after</li><li>insertAfter<ul><li>将元素添加到指定元素外部的后面</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 1.创建一个节点</span><span class="token keyword">var</span> $li <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"&lt;li&gt;新增的li&lt;/li&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 2.添加节点</span><span class="token comment">// $("ul").after($li);</span>$li<span class="token punctuation">.</span><span class="token function">insertAfter</span><span class="token punctuation">(</span><span class="token string">"ul"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><ul><li>before</li><li>insertBefore<ul><li>将元素添加到指定元素外部的前面</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 1.创建一个节点</span><span class="token keyword">var</span> $li <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"&lt;li&gt;新增的li&lt;/li&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 2.添加节点</span><span class="token comment">// $("ul").before($li);</span>$li<span class="token punctuation">.</span><span class="token function">insertBefore</span><span class="token punctuation">(</span><span class="token string">"ul"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><h4><a id="2__1673"></a>2. 删除节点</h4><ul><li>empty()<ul><li>删除指定元素的内容和子元素, 指定元素自身不会被删除</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><ul><li>remove()<ul><li>删除指定元素</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 删除所有div</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 删除div中id是box1的那个div</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token string">"#box1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre><ul><li>detach()</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 删除所有div</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">detach</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 删除div中id是box1的那个div</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">detach</span><span class="token punctuation">(</span><span class="token string">"#box1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre><ul><li>remove和detach区别<ul><li>remove删除元素后,元素上的事件会被移出</li><li>detach删除元素后,元素上的事件会被保留</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// $("div").remove();</span>    <span class="token comment">// $("div").empty();</span>    <span class="token comment">// $("li").remove(".item");</span><pre><code>&lt;span class=&quot;token comment&quot;&gt;// 利用remove删除之后再重新添加,原有的事件无法响应&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// var $div = $(&quot;div&quot;).remove();&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 利用detach删除之后再重新添加,原有事件可以响应&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $div &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;detach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// console.log($div);&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// 将删除的返回值重新添加到body上&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$div&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">“div”</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br>    <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">“div被点击了”</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li></ul></pre><h4><a id="3__1716"></a>3. 替换节点</h4><ul><li>replaceWith<ul><li>将所有匹配的元素替换成指定的HTML或DOM元素</li><li>replaceWith参数可以是一个DOM元素</li><li>replaceWith参数也可以是一个代码片段</li></ul></li><li>replaceAll<ul><li>用匹配的元素替换掉所有 selector匹配到的元素</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 编写jQuery相关代码</span><span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// 创建一个新的节点</span>    <span class="token keyword">var</span> $item <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"&lt;h6&gt;我是标题6&lt;/h6&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token comment">// 利用新的节点替换旧的节点</span>    <span class="token comment">// $("h1").replaceWith($item);</span>    $item<span class="token punctuation">.</span><span class="token function">replaceAll</span><span class="token punctuation">(</span><span class="token string">"h1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li></ul></pre><h4><a id="4__1734"></a>4. 复制节点</h4><ul><li>clone<ul><li>复制一个节点</li><li>浅复制不会复制节点的事件</li><li>深复制会复制节点的事件</li></ul></li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// clone([Even[,deepEven]])</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 1.浅复制一个元素</span>        <span class="token keyword">var</span> $li <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"li:first"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token comment">// 2.将复制的元素添加到ul中</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"ul"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>$li<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 点击li无法响应事件</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eq</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// 1.深复制一个元素</span>        <span class="token keyword">var</span> $li <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"li:first"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token comment">// 2.将复制的元素添加到ul中</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"ul"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>$li<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 点击li可以响应事件</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><pre><code>&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;li&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#123;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#125;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre><p><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li></ul></pre><h4><a id="5__1760"></a>5. 包裹节点</h4><ul><li>wrap()<ul><li>将指定节点用其他标记包裹起来</li><li>该方法对于需要在文档中插入额外的结构化标记非常有用, 而且不会破坏原始文档的语义</li></ul></li><li>wrapAll()<ul><li>将所有匹配的元素用一个元素来包裹</li><li>而 wrap() 方法是将所有的元素进行单独包裹</li></ul></li><li>wrapInner()<ul><li>将每一个匹配的元素的子内容（包括文本节点）用其他结构化标记包裹起来</li></ul></li></ul><pre class="prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text/javascript<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">    <span class="token comment">//测试使用 jQuery wrap, wrapAll, wrapInner</span>    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>        <span class="token comment">//包装 li 本身</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#box1 li"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">wrap</span><span class="token punctuation">(</span><span class="token string">"&lt;font color='red'&gt;&lt;/font&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token comment">//包装所有的 li</span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#box2 li"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">wrapAll</span><span class="token punctuation">(</span><span class="token string">"&lt;font color='red'&gt;&lt;/font&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token comment">//包装 li 里边的文字. </span>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#box3 li"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">wrapInner</span><span class="token punctuation">(</span><span class="token string">"&lt;font color='red'&gt;&lt;/font&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li></ul></pre><h4><a id="6__1785"></a>6. 遍历节点</h4><ul><li>children() ：只考虑子元素，不考虑后代元素。</li><li>next() ：同辈紧邻后面一个元素。</li><li>nextAll() ：同辈紧邻后面所有兄弟元素。</li><li>prev() ：同辈紧邻前一个兄弟元素。</li><li>prevAll() ：同辈紧邻前所有兄弟元素。</li><li>siblings() ：同辈所有兄弟元素。</li><li>find(‘span’) ：返回被选元素的后代元素，括号内必填写，如果查找所有后代使用 “*”，起查找作用。</li><li>filter(‘div’) ：指定选择器的xx元素，括号内必填写，符合条件的同级元素，非后代元素，起过滤作用。</li><li>has(‘div’) ：符合条件的后代元素，不包含自身，括号内必填写，起过滤作用。</li><li>parents() ：获取所有祖先元素，参数为筛选条件。</li><li>closest(‘.new’) ：用来取得最近的匹配元素，包括自身。<ul><li>首选检查自身是否符合，如果符合返回元素本身；如果不匹配，向上查找父元素，逐级向上直到匹配到选择器的元素。</li><li>如果什么没找到，返回一个空的jq对象。必须填写筛选条件，且只能找到一个元素。</li></ul></li><li>parentsUntil() ：截止到xx位置的祖先节点。</li></ul><h2><a name="t13"></a><a id="13_jQuery__1800"></a>13. jQuery 面试题</h2><h4><a id="1_jQueryjquery_1801"></a>1. 为什么要使用jQuery？jquery有哪些好处？</h4><ul><li>jQuery是轻量级的框架</li><li>强大的选择器，出色的DOM操作的封装</li><li>可靠的事件处理机制（jQuery在处理事件绑定的时候相当的可靠）</li><li>ajax封装的非常的好，不需要考虑复杂浏览器的兼容性和XMLHttpRequest对象的创建和使用的问题</li><li>出色的浏览器的兼容性</li><li>支持链式操作，隐式迭代</li><li>行为层和结构层的分离，还支持丰富的插件，jquery 的文档也非常的丰富</li></ul><h4><a id="2_jQuery_1810"></a>2. jQuery能做什么？</h4><ul><li>获取页面的元素</li><li>修改页面的外观</li><li>改变页面大的内容</li><li>响应用户的页面操作</li><li>为页面添加动态效果</li><li>无需刷新页面，即可以从服务器获取信息</li><li>简化常见的javascript任务</li></ul><h4><a id="3_jQuery____1818"></a>3. jQuery 库中的 $() 是什么？</h4><ul><li>$() 函数是 jQuery() 函数的别称</li><li>$() 函数用于将任何对象包裹成 jQuery 对象</li><li>允许调用定义在 jQuery 对象上的多个不同方法</li></ul><h4><a id="4_documentready__1823"></a>4. $(document).ready() 是个什么函数？为什么要用它？</h4><ul><li>ready() 函数用于在文档进入ready状态时执行代码</li><li>当DOM 完全加载（例如HTML被完全解析DOM树构建完成时），jQuery允许你执行代码</li><li>使用$(document).ready()的最大好处在于它适用于所有浏览器，jQuery帮你解决了跨浏览器的难题</li></ul><h4><a id="5_documentreadywindowonload_1828"></a>5. (document).ready()方法和window.onload有什么区别？</h4><ul><li>window.onload方法是在网页中所有的元素完全加载到浏览器后才执行</li><li>$(document).ready() 可以在DOM载入就绪是就对其进行操纵，并调用执行绑定的函数</li></ul><h4><a id="6_jQuerygetpost_1832"></a>6. jQuery中.get()提交和.post()提交的区别</h4><ul><li>.get()使用GET方法来进行异步提交，.post()使用POST方法来进行异步提交</li><li>get请求方式将参数跟在url后进行传递用户可见 post请求则是作为http消息的实体内容发送给服务器，用户不可见</li><li>post传输数据比get大</li><li>get请求的数据会被浏览器缓存，不安全</li></ul><h4><a id="7_jQuery_1838"></a>7. jQuery中有哪些方法可以遍历节点？</h4><ul><li>children():获取匹配元素的子元素集合，不考虑后代元素 <span class="katex--inline">KaTeX parse error: Expected '}', got 'EOF' at end of input: (function(){</span>(“div”).children()})</li><li>next()获取匹配元素后面紧邻的同级元素</li><li>prev()获取匹配元素前紧邻的同级元素</li><li>siblings()获取匹配元素前后的所有同辈元素</li></ul><h4><a id="8_this__this__jQuery__1844"></a>8. $(this) 和 this 关键字在 jQuery 中有何不同？</h4><ul><li>$(this) 返回一个 jQuery 对象，可以对它调用多个 jQuery 方法</li><li>this 代表当前元素，它是 JavaScript 关键词中的一个，表示上下文中的当前 DOM 元素。</li><li>不能对 this 调用 jQuery 方法，直到 this 被 $() 函数包裹，例如 $(this)。</li></ul><h4><a id="9__CDN__jQuery___1849"></a>9. 使用 CDN 加载 jQuery 库的主要优势是什么 ?</h4><ul><li>报错节省服务器带宽</li><li>更快的下载速度</li><li>如果浏览器已经从同一个CDN下载类相同的 jQuery 版本, 那么它就不会再去下载它一次</li></ul><h4><a id="10__1854"></a>10. 如何使用从服务器获取一个复杂数据(对象)?</h4><ul><li>通常会把这个数据转换为通用的数据交换格式，如xml或json。由于xml解析比较麻烦，所以使用json比较多。</li><li>在jQuery中有专门的获取服务器json数据的方法，getJSON()，在回调中，jQuery会自动将json转换为java对象。</li></ul><h4><a id="11__1858"></a>11. 在使用选择器的时要注意的地方?</h4><ul><li>选择器中含有\等特殊字符的时候需要进行转译</li><li>属性选择器的引号问题</li><li>选择器中含有空格的注意事项</li></ul><h4><a id="12__1863"></a>12. 有哪些查询节点的选择器？</h4><ul><li>:first 查询第一个</li><li>:last 查询最后一个，</li><li>:odd查询奇数但是索引从0开始</li><li>:even 查询偶数</li><li>:eq(index)查询相等的</li><li>:gt(index)查询大于index的</li><li>:lt查询小于index</li><li>:header 选取所有的标题等</li></ul><h4><a id="13_jQuery____1873"></a>13. jQuery是如何处理缓存的？ ( 要处理缓存就是禁用缓存 )</h4><ul><li>通过<code>$.post()</code>方法来获取数据，那么默认就是禁用缓存的</li><li>通过<code>$.get()</code>方法来获取数据，可以通过设置时间戳来避免缓存。 可以在URL后面加上+(+new Date)</li></ul><pre class="prettyprint"><code class="prism language-js has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">$<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'ajax.xml?'</span><span class="token operator">+</span><span class="token punctuation">(</span><span class="token operator">+</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token comment">//内容&#125;);</span><div class="hljs-button &#123;2&#125;" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre><ul><li>通过<code>$.ajax</code>方法来获取数据，只要设置cache:false即可。</li></ul><h4><a id="14_jquery_1881"></a>14. 在jquery中你有没有编写过插件，插件有什么好处？你编写过那些插件？它应该注意那些？</h4><ul><li><strong>插件的好处 :</strong><ul><li>对已有的一系列方法或函数的封装，以便在其他地方重新利用</li><li>方便后期维护和提高开发效率插件的分类：封装对象方法插件、封装全局函数插件、选择器插件</li></ul></li><li><strong>注意的地方：</strong><ul><li>插件的文件名推荐命名为jquery.[插件名].js，以免和其他的javaScript库插件混淆</li><li>所有的对象方法都应当附加到jQuery.fn对象上，而所有的全局函数都应当附加到jQuery对象本身上</li><li>插件应该返回一个jQuery对象，以保证插件的可链式操作</li><li>避免在插件内部使用$作为jQuery对象的别名,而应使用完整的jQuery来表示，这样可以避免冲突或使用闭包来避免</li><li>所有的方法或函数插件，都应当分好结尾，否则压缩的时候可能出现问题。在插件头部加上分号，这样可以避免他人的不规范代码给插件带来影响</li><li>在插件中通过<code>$.extent(&#123;&#125;)</code>封装全局函数,选择器插件，扩展已有的object对象过<code>$.fn.extend(&#123;&#125;)</code>封装对象方法插件</li></ul></li></ul><pre><code>                                &lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jQuery中的效果</title>
      <link href="front/jquery/jquery-effect/"/>
      <url>front/jquery/jquery-effect/</url>
      
        <content type="html"><![CDATA[<h3 id="jQuery-效果函数"><a href="#jQuery-效果函数" class="headerlink" title="jQuery 效果函数"></a>jQuery 效果函数</h3><table class="dataintable"><tbody><tr><th>方法</th><th>描述</th></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_animate.asp" title="jQuery 效果 - animate() 方法">animate()</a></td><td>对被选元素应用“自定义”的动画</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_clearqueue.asp" title="jQuery 效果 - clearQueue() 方法">clearQueue()</a></td><td>对被选元素移除所有排队的函数（仍未运行的）</td></tr><tr><td>delay()</td><td>对被选元素的所有排队函数（仍未运行）设置延迟</td></tr><tr><td>dequeue()</td><td>运行被选元素的下一个排队函数</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_fadein.asp" title="jQuery 效果 - fadeIn() 方法">fadeIn()</a></td><td>逐渐改变被选元素的不透明度，从隐藏到可见</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_fadeout.asp" title="jQuery 效果 - fadeOut() 方法">fadeOut()</a></td><td>逐渐改变被选元素的不透明度，从可见到隐藏</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_fadeto.asp" title="jQuery 效果 - fadeTo() 方法">fadeTo()</a></td><td>把被选元素逐渐改变至给定的不透明度</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_hide.asp" title="jQuery 效果 - hide() 方法">hide()</a></td><td>隐藏被选的元素</td></tr><tr><td>queue()</td><td>显示被选元素的排队函数</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_show.asp" title="jQuery 效果 - show() 方法">show()</a></td><td>显示被选的元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_slidedown.asp" title="jQuery 效果 - slideDown() 方法">slideDown()</a></td><td>通过调整高度来滑动显示被选元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_slidetoggle.asp" title="jQuery 效果 - slideToggle() 方法">slideToggle()</a></td><td>对被选元素进行滑动隐藏和滑动显示的切换</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_slideup.asp" title="jQuery 效果 - slideUp() 方法">slideUp()</a></td><td>通过调整高度来滑动隐藏被选元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_stop.asp" title="jQuery 效果 - stop() 方法">stop()</a></td><td>停止在被选元素上运行动画</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/effect_toggle.asp" title="jQuery 效果 - toggle() 方法">toggle()</a></td><td>对被选元素进行隐藏和显示的切换</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jQuery中的事件</title>
      <link href="front/jquery/jquery-event/"/>
      <url>front/jquery/jquery-event/</url>
      
        <content type="html"><![CDATA[<h3 id="jQuery-事件方法"><a href="#jQuery-事件方法" class="headerlink" title="jQuery 事件方法"></a>jQuery 事件方法</h3><p>事件方法会触发匹配元素的事件，或将函数绑定到所有匹配元素的某个事件。</p><h3 id="触发实例："><a href="#触发实例：" class="headerlink" title="触发实例："></a>触发实例：</h3><p><code>$(&quot;button#demo&quot;).click()</code><br>上面的例子将触发 id=”demo” 的 button 元素的 click 事件。</p><h3 id="绑定实例："><a href="#绑定实例：" class="headerlink" title="绑定实例："></a>绑定实例：</h3><p><code>$(&quot;button#demo&quot;).click(function()&#123;$(&quot;img&quot;).hide()&#125;)</code><br>上面的例子会在点击 id=”demo” 的按钮时隐藏所有图像。</p><table class="dataintable"><tbody><tr><th style="width:35%;">方法</th><th>描述</th></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_bind.asp" title="jQuery 事件 - bind() 方法">bind()</a></td><td>向匹配元素附加一个或更多事件处理器</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_blur.asp" title="jQuery 事件 - blur() 方法">blur()</a></td><td>触发、或将函数绑定到指定元素的 blur 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_change.asp" title="jQuery 事件 - change() 方法">change()</a></td><td>触发、或将函数绑定到指定元素的 change 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_click.asp" title="jQuery 事件 - click() 方法">click()</a></td><td>触发、或将函数绑定到指定元素的 click 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_dblclick.asp" title="jQuery 事件 - dblclick() 方法">dblclick()</a></td><td>触发、或将函数绑定到指定元素的 double click 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_delegate.asp" title="jQuery 事件 - delegate() 方法">delegate()</a></td><td>向匹配元素的当前或未来的子元素附加一个或多个事件处理器</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_die.asp" title="jQuery 事件 - die() 方法">die()</a></td><td>移除所有通过 live() 函数添加的事件处理程序。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_error.asp" title="jQuery 事件 - error() 方法">error()</a></td><td>触发、或将函数绑定到指定元素的 error 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_isdefaultprevented.asp" title="jQuery 事件 - isDefaultPrevented() 方法">event.isDefaultPrevented()</a></td><td>返回 event 对象上是否调用了 event.preventDefault()。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_pagex.asp" title="jQuery 事件 - pageX 属性">event.pageX</a></td><td>相对于文档左边缘的鼠标位置。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_pagey.asp" title="jQuery 事件 - pageY 属性">event.pageY</a></td><td>相对于文档上边缘的鼠标位置。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_preventdefault.asp" title="jQuery 事件 - preventDefault() 方法">event.preventDefault()</a></td><td>阻止事件的默认动作。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_result.asp" title="jQuery 事件 - result 属性">event.result</a></td><td>包含由被指定事件触发的事件处理器返回的最后一个值。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_target.asp" title="jQuery 事件 - target 属性">event.target</a></td><td>触发该事件的 DOM 元素。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_timeStamp.asp" title="jQuery 事件 - timeStamp 属性">event.timeStamp</a></td><td>该属性返回从 1970 年 1 月 1 日到事件发生时的毫秒数。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_type.asp" title="jQuery 事件 - type 属性">event.type</a></td><td>描述事件的类型。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_which.asp" title="jQuery 事件 - which 属性">event.which</a></td><td>指示按了哪个键或按钮。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_focus.asp" title="jQuery 事件 - focus() 方法">focus()</a></td><td>触发、或将函数绑定到指定元素的 focus 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_keydown.asp" title="jQuery 事件 - keydown() 方法">keydown()</a></td><td>触发、或将函数绑定到指定元素的 key down 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_keypress.asp" title="jQuery 事件 - keypress() 方法">keypress()</a></td><td>触发、或将函数绑定到指定元素的 key press 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_keyup.asp" title="jQuery 事件 - keyup() 方法">keyup()</a></td><td>触发、或将函数绑定到指定元素的 key up 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_live.asp" title="jQuery 事件 - live() 方法">live()</a></td><td>为当前或未来的匹配元素添加一个或多个事件处理器</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_load.asp" title="jQuery 事件 - load() 方法">load()</a></td><td>触发、或将函数绑定到指定元素的 load 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_mousedown.asp" title="jQuery 事件 - mousedown() 方法">mousedown()</a></td><td>触发、或将函数绑定到指定元素的 mouse down 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_mouseenter.asp" title="jQuery 事件 - mouseenter() 方法">mouseenter()</a></td><td>触发、或将函数绑定到指定元素的 mouse enter 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_mouseleave.asp" title="jQuery 事件 - mouseleave() 方法">mouseleave()</a></td><td>触发、或将函数绑定到指定元素的 mouse leave 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_mousemove.asp" title="jQuery 事件 - mousemove() 方法">mousemove()</a></td><td>触发、或将函数绑定到指定元素的 mouse move 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_mouseout.asp" title="jQuery 事件 - mouseout() 方法">mouseout()</a></td><td>触发、或将函数绑定到指定元素的 mouse out 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_mouseover.asp" title="jQuery 事件 - mouseover() 方法">mouseover()</a></td><td>触发、或将函数绑定到指定元素的 mouse over 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_mouseup.asp" title="jQuery 事件 - mouseup() 方法">mouseup()</a></td><td>触发、或将函数绑定到指定元素的 mouse up 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_one.asp" title="jQuery 事件 - one() 方法">one()</a></td><td>向匹配元素添加事件处理器。每个元素只能触发一次该处理器。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_ready.asp" title="jQuery 事件 - ready() 方法">ready()</a></td><td>文档就绪事件（当 HTML 文档就绪可用时）</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_resize.asp" title="jQuery 事件 - resize() 方法">resize()</a></td><td>触发、或将函数绑定到指定元素的 resize 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_scroll.asp" title="jQuery 事件 - scroll() 方法">scroll()</a></td><td>触发、或将函数绑定到指定元素的 scroll 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_select.asp" title="jQuery 事件 - select() 方法">select()</a></td><td>触发、或将函数绑定到指定元素的 select 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_submit.asp" title="jQuery 事件 - submit() 方法">submit()</a></td><td>触发、或将函数绑定到指定元素的 submit 事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_toggle.asp" title="jQuery 事件 - toggle() 方法">toggle()</a></td><td>绑定两个或多个事件处理器函数，当发生轮流的 click 事件时执行。</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_trigger.asp" title="jQuery 事件 - trigger() 方法">trigger()</a></td><td>所有匹配元素的指定事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_triggerhandler.asp" title="jQuery 事件 - triggerHandler() 方法">triggerHandler()</a></td><td>第一个被匹配元素的指定事件</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_unbind.asp" title="jQuery 事件 - unbind() 方法">unbind()</a></td><td>从匹配元素移除一个被添加的事件处理器</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_undelegate.asp" title="jQuery 事件 - undelegate() 方法">undelegate()</a></td><td>从匹配元素移除一个被添加的事件处理器，现在或将来</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/event_unload.asp" title="jQuery 事件 - unload() 方法">unload()</a></td><td>触发、或将函数绑定到指定元素的 unload 事件</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jQuery中的选择器</title>
      <link href="front/jquery/jquery-selector/"/>
      <url>front/jquery/jquery-selector/</url>
      
        <content type="html"><![CDATA[<h3 id="jq选择器大全"><a href="#jq选择器大全" class="headerlink" title="jq选择器大全"></a>jq选择器大全</h3><table class="dataintable"><tbody><tr><th>选择器</th><th>实例</th><th>选取</th></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_all.asp" title="jQuery * 选择器">*</a></td><td>$("*")</td><td>所有元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_id.asp" title="jQuery # 选择器">#<i>id</i></a></td><td>$("#lastname")</td><td>id="lastname" 的元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_class.asp" title="jQuery . 选择器">.<i>class</i></a></td><td>$(".intro")</td><td>所有 class="intro" 的元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_element.asp" title="jQuery element 选择器"><i>element</i></a></td><td>$("p")</td><td>所有 &lt;p&gt; 元素</td></tr><tr><td>.<i>class</i>.<i>class</i></td><td>$(".intro.demo")</td><td>所有 class="intro" 且 class="demo" 的元素</td></tr><tr><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_first.asp" title="jQuery :first 选择器">:first</a></td><td>$("p:first")</td><td>第一个 &lt;p&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_last.asp" title="jQuery :last 选择器">:last</a></td><td>$("p:last")</td><td>最后一个 &lt;p&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_even.asp" title="jQuery :even 选择器">:even</a></td><td>$("tr:even")</td><td>所有偶数 &lt;tr&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_odd.asp" title="jQuery :odd 选择器">:odd</a></td><td>$("tr:odd")</td><td>所有奇数 &lt;tr&gt; 元素</td></tr><tr><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_eq.asp" title="jQuery :eq() 选择器">:eq(<i>index</i>)</a></td><td>$("ul li:eq(3)")</td><td>列表中的第四个元素（index 从 0 开始）</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_gt.asp" title="jQuery :gt 选择器">:gt(<i>no</i>)</a></td><td>$("ul li:gt(3)")</td><td>列出 index 大于 3 的元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_lt.asp" title="jQuery :lt 选择器">:lt(<i>no</i>)</a></td><td>$("ul li:lt(3)")</td><td>列出 index 小于 3 的元素</td></tr><tr><td>:not(<i>selector</i>)</td><td>$("input:not(:empty)")</td><td>所有不为空的 input 元素</td></tr><tr><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_header.asp" title="jQuery :header 选择器">:header</a></td><td>$(":header")</td><td>所有标题元素 &lt;h1&gt; - &lt;h6&gt;</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_animated.asp" title="jQuery :animated 选择器">:animated</a></td><td>&nbsp;</td><td>所有动画元素</td></tr><tr><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_contains.asp" title="jQuery :contains 选择器">:contains(<i>text</i>)</a></td><td>$(":contains('W3School')")</td><td>包含指定字符串的所有元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_empty.asp" title="jQuery :empty 选择器">:empty</a></td><td>$(":empty")</td><td>无子（元素）节点的所有元素</td></tr><tr><td>:hidden</td><td>$("p:hidden")</td><td>所有隐藏的 &lt;p&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_visible.asp" title="jQuery :visible 选择器">:visible</a></td><td>$("table:visible")</td><td>所有可见的表格</td></tr><tr><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td></tr><tr><td>s1,s2,s3</td><td>$("th,td,.intro")</td><td>所有带有匹配选择的元素</td></tr><tr><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_attribute.asp" title="jQuery [attribute] 选择器">[<i>attribute</i>]</a></td><td>$("[href]")</td><td>所有带有 href 属性的元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_attribute_equal_value.asp" title="jQuery [attribute=value] 选择器">[<i>attribute</i>=<i>value</i>]</a></td><td>$("[href='#']")</td><td>所有 href 属性的值等于 "#" 的元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_attribute_notequal_value.asp" title="jQuery [attribute!=value] 选择器">[<i>attribute</i>!=<i>value</i>]</a></td><td>$("[href!='#']")</td><td>所有 href 属性的值不等于 "#" 的元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_attribute_end_value.asp" title="jQuery [attribute$=value] 选择器">[<i>attribute</i>$=<i>value</i>]</a></td><td>$("[href$='.jpg']")</td><td>所有 href 属性的值包含以 ".jpg" 结尾的元素</td></tr><tr><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input.asp" title="jQuery :input 选择器">:input</a></td><td>$(":input")</td><td>所有 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_text.asp" title="jQuery :text 选择器">:text</a></td><td>$(":text")</td><td>所有 type="text" 的 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_password.asp" title="jQuery :password 选择器">:password</a></td><td>$(":password")</td><td>所有 type="password" 的 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_radio.asp" title="jQuery :radio 选择器">:radio</a></td><td>$(":radio")</td><td>所有 type="radio" 的 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_checkbox.asp" title="jQuery :checkbox 选择器">:checkbox</a></td><td>$(":checkbox")</td><td>所有 type="checkbox" 的 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_submit.asp" title="jQuery :submit 选择器">:submit</a></td><td>$(":submit")</td><td>所有 type="submit" 的 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_reset.asp" title="jQuery :reset 选择器">:reset</a></td><td>$(":reset")</td><td>所有 type="reset" 的 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_button.asp" title="jQuery :button 选择器">:button</a></td><td>$(":button")</td><td>所有 type="button" 的 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_image.asp" title="jQuery :image 选择器">:image</a></td><td>$(":image")</td><td>所有 type="image" 的 &lt;input&gt; 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_file.asp" title="jQuery :file 选择器">:file</a></td><td>$(":file")</td><td>所有 type="file" 的 &lt;input&gt; 元素</td></tr><tr><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td><td style="background-color:#fff;">&nbsp;</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_enabled.asp" title="jQuery :enabled 选择器">:enabled</a></td><td>$(":enabled")</td><td>所有激活的 input 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_disabled.asp" title="jQuery :disabled 选择器">:disabled</a></td><td>$(":disabled")</td><td>所有禁用的 input 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_selected.asp" title="jQuery :selected 选择器">:selected</a></td><td>$(":selected")</td><td>所有被选取的 input 元素</td></tr><tr><td><a href="https://www.w3school.com.cn/jquery/selector_input_checked.asp" title="jQuery :checked 选择器">:checked</a></td><td>$(":checked")</td><td>所有被选中的 input 元素</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
            <tag> jQuery </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>websocket初识</title>
      <link href="front/socket/websocket-introduce/"/>
      <url>front/socket/websocket-introduce/</url>
      
        <content type="html"><![CDATA[<p>套接字（socket）是一个抽象层，应用程序可以通过它发送或接收数据，可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中，并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。</p><h3 id="websocket的基本概念"><a href="#websocket的基本概念" class="headerlink" title="websocket的基本概念"></a>websocket的基本概念</h3><p>websocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器（full-duplex）通信-允许服务区主动发送信息给客户端。</p><p>websocket是一种持久协议，http是非持久协议</p><p>现在很多网站都有实施推送的需求，比如聊天，客服咨询等</p><p>早期没有websocket时，通过ajax轮询</p><p>websocket是一种网络协议，允许客户端和服务端全双工的进行网络通信。服务器可以给客户端发消息，客户端也可以给服务端发消息。</p><p>这种方式十分节省性能<br>要是ajax轮循，http的握手过程是十分耗性能的</p><h3 id="在H5中，如何使用websocket"><a href="#在H5中，如何使用websocket" class="headerlink" title="在H5中，如何使用websocket"></a>在H5中，如何使用websocket</h3><h3 id="websocket事件"><a href="#websocket事件" class="headerlink" title="websocket事件"></a>websocket事件</h3><table><thead><tr><th>事件</th><th>事件处理程序</th><th>描述</th></tr></thead><tbody><tr><td>open</td><td>Socket.onopen</td><td>连接建立时触发</td></tr><tr><td>message</td><td>Socket.onmessage</td><td>客户端接受服务端数据时触发</td></tr><tr><td>error</td><td>Socket.onerror</td><td>通信发生错误时触发</td></tr><tr><td>close</td><td>Socket.onclose</td><td>连接关闭时触发</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> socket </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue.js的安装</title>
      <link href="front/vue/old/vue-install/"/>
      <url>front/vue/old/vue-install/</url>
      
        <content type="html"><![CDATA[<h3 id="咱先说说关于兼容性的问题"><a href="#咱先说说关于兼容性的问题" class="headerlink" title="咱先说说关于兼容性的问题"></a>咱先说说关于兼容性的问题</h3><p>Vue 不支持 IE8 及以下版本，因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持<a href="https://caniuse.com/#feat=es5">所有兼容 ECMAScript 5 的浏览器。</a></p><h3 id="lt-script-gt-标签直接引入"><a href="#lt-script-gt-标签直接引入" class="headerlink" title="&lt;script&gt;标签直接引入"></a><code>&lt;script&gt;</code>标签直接引入</h3><p>直接用 <code>&lt;script&gt;</code> 引入<br>直接下载并用 <code>&lt;script&gt;</code> 标签引入，Vue 会被注册为一个全局变量。  </p><p>这里小编推荐给新手朋友们两种快速简单的方式  </p><h3 id="本地文件引入"><a href="#本地文件引入" class="headerlink" title="本地文件引入"></a>本地文件引入</h3><ol><li>你可以在vue的官网中找到，或者直接点击下面的链接  </li></ol><p>在这里小编给大家提供了两个版本：  </p><div style="width: 300px; height: 50px; border-radius: 50px; background-color: #42b983; font-size: 24px;"><a href="https://cn.vuejs.org/js/vue.js"><p style="color:#eef; line-height:50px;text-align: center;">开发版本</p></a></div>这个版本包含完整的警告和调试模式，适用于开发和学习中使用  <div style="width: 300px; height: 50px; border-radius: 50px; background-color: #42b983; font-size: 24px;"><a href="https://cn.vuejs.org/js/vue.min.js"><p style="color:#eef; line-height:50px;text-align: center;">生产版本</p></a></div>这个版本适合用于上线的项目，因为这里做了一些压缩和优化，会为你提升性能  <p>使用时在页面中复制所有代码，存入到本地的文件中，直接在<code>&lt;script&gt;</code>标签中引入文件即可  </p><h3 id="内容分发网络（CDN）方式引入"><a href="#内容分发网络（CDN）方式引入" class="headerlink" title="内容分发网络（CDN）方式引入"></a>内容分发网络（CDN）方式引入</h3><ol start="2"><li>使用CDN方式导入</li></ol><ul><li><p>对于制作原型或学习，你可以这样使用最新版本：<br><code>&lt;script src=&quot;https://cdn.jsdelivr.net/npm/vue&quot;&gt;&lt;/script&gt;</code></p></li><li><p>对于生产环境，我们推荐链接到一个明确的版本号和构建文件，以避免新版本造成的不可预期的破坏：<br><code>&lt;script src=&quot;https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js&quot;&gt;&lt;/script&gt;</code>  </p></li><li><p>如果你使用原生 ES Modules，这里也有一个兼容 ES Module 的构建文件：  </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;script type&#x3D;&quot;module&quot;&gt;</span><br><span class="line">  import Vue from &#39;https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;npm&#x2F;vue@2.6.10&#x2F;dist&#x2F;vue.esm.browser.js&#39;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure></li></ul><h3 id="NPM方式"><a href="#NPM方式" class="headerlink" title="NPM方式"></a>NPM方式</h3><p>在用 Vue 构建大型应用时推荐使用 NPM 安装。NPM 能很好地和诸如 <a href="https://webpack.js.org/">webpack</a> 或 <a href="http://browserify.org/">Browserify</a> 模块打包器配合使用。同时 Vue 也提供配套工具来开发<a href="https://cn.vuejs.org/v2/guide/single-file-components.html">单文件组件</a>。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 最新稳定版</span><br><span class="line">$ npm install vue</span><br></pre></td></tr></table></figure><h3 id="最后送你一个小彩蛋-Vue-Devtools"><a href="#最后送你一个小彩蛋-Vue-Devtools" class="headerlink" title="最后送你一个小彩蛋-Vue Devtools"></a>最后送你一个小彩蛋-Vue Devtools</h3><p>在使用 Vue 时，我们推荐在你的浏览器上安装 <a href="https://github.com/vuejs/vue-devtools#vue-devtools">Vue Devtools</a>。它允许你在一个更友好的界面中审查和调试 Vue 应用</p><p><a href="https://www.cnblogs.com/yuqing6/p/7440549.html">vue调试工具vue-devtools安装及使用</a></p><style type="text/css">        </style>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> web </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Vue.js简单介绍</title>
      <link href="front/vue/old/vue-introduce/"/>
      <url>front/vue/old/vue-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="首先我们来说说-Vue-js-是什么"><a href="#首先我们来说说-Vue-js-是什么" class="headerlink" title="首先我们来说说 Vue.js 是什么"></a>首先我们来说说 Vue.js 是什么</h3><p>Vue.js 一句话来说：就是一套用于构建用户界面的渐进式框架。</p><p>渐进式是重点，什么是渐进式，就是说你可以从简单到复杂的逐渐的学习和使用它。</p><p>与其它大型框架不同的是，Vue 被设计为可以自底向上逐层应用。</p><p>Vue 的核心库只关注视图层，不仅易于上手，还便于与第三方库或既有项目整合。</p><p>另一方面，当与<a href="https://cn.vuejs.org/v2/guide/single-file-components.html">现代化的工具链</a>以及各种<a href="https://github.com/vuejs/awesome-vue#libraries--plugins">支持类库</a>结合使用时，Vue 也完全能够为复杂的单页应用提供驱动。</p><h3 id="Vue-js-优点（吹nb部分）"><a href="#Vue-js-优点（吹nb部分）" class="headerlink" title="Vue.js 优点（吹nb部分）"></a>Vue.js 优点（吹nb部分）</h3><ul><li>体积小<br>压缩后33K，小吧！</li><li>更高的运行效率<br>基于虚拟dom，一种可以预先通过js进行各种计算，把最终的DOM操作计算出来并优化的技术，由于这个DOM操作属于预处理操作，并没有真实的操作DOM，所以叫做虚拟DOM  </li><li>双向数据绑定<br>让开发者不用再去操作DOM对象，把更多的精力投入到你自己的业务逻辑上去  </li><li>生态丰富，学习成本低<br>市场上拥有大量成熟，稳定的基于vue.js的ui框架，常用组件，拿来即可使用并实现快速开发！</li></ul><p><code>对初学者友好，入门容易，学习资料多；</code></p><h3 id="vue-js-前段开发人员必修技能"><a href="#vue-js-前段开发人员必修技能" class="headerlink" title="vue.js - 前段开发人员必修技能"></a>vue.js - 前段开发人员必修技能</h3><ul><li>使用场景广泛<br>被广泛的应用于Web端，移动端，跨平台应用开发  </li><li>招聘市场需求大，前景较好</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
            <tag> vue </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于deepin系统不能识别蓝牙设备问题的完美解决方案</title>
      <link href="linux/deepin-bluetooth/"/>
      <url>linux/deepin-bluetooth/</url>
      
        <content type="html"><![CDATA[<h3 id="为Deepin-Linux启用蓝牙支持"><a href="#为Deepin-Linux启用蓝牙支持" class="headerlink" title="为Deepin Linux启用蓝牙支持"></a>为Deepin Linux启用蓝牙支持</h3><p>自从安装了Deepin Linux，并采用自己编译的内核后，笔者的ThinkPad X200笔记本体验可谓是上升了一个非常重要的层次。后来有一天，笔者想用蓝牙耳机听音乐，然而在使用过程中发现，这台笔记本虽然自带蓝牙，屏幕下的蓝牙指示灯一直点亮着，系统中却看不到与蓝牙有关的设置选项。<br>出现这样的问题，多半就是因为系统中对蓝牙的支持没有启用，主要包括系统组件和内核两个层面。下面把我的经验总结如下。</p><h3 id="安装蓝牙组件"><a href="#安装蓝牙组件" class="headerlink" title="安装蓝牙组件"></a>安装蓝牙组件</h3><p>默认地，Deepin并没有在系统中装上蓝牙组件，须用户手动安装。在终端中运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install bluetooth blueman</span><br></pre></td></tr></table></figure><p>其中，<code>bluetooth</code>是Linux蓝牙的核心组件，而<code>blueman</code>则是基于GTK+的一个全功能蓝牙管理器。把它们一齐装上，即可为Deepin启用全面的蓝牙支持。</p><h3 id="配置内核"><a href="#配置内核" class="headerlink" title="配置内核"></a>配置内核</h3><p>笔者本以为安装了蓝牙组件后，蓝牙功能就能正常使用（因为之前在解决WLAN问题时，WLAN驱动未配置的情况下无线网卡灯是不会亮的，然而蓝牙灯始终会常亮），但是当打开蓝牙管理器时，竟然报错，提示蓝牙服务未启动。这不得不让我想到，内核中的蓝牙支持是否没有启用。<br>果不其然。在内核源码目录下运行<code>make menuconfig</code>，打开内核配置界面，依次对内核进行以下配置。</p><h3 id="1、启用蓝牙支持"><a href="#1、启用蓝牙支持" class="headerlink" title="1、启用蓝牙支持"></a>1、启用蓝牙支持</h3><p>内核中的蓝牙选项位于【Network Settings】 –&gt; 【Bluetooth subsystem support】。先选中【Bluetooth subsystem support】，然后按”Y“，勾选它。</p><p><img src= "/img/loading.gif" data-lazy-src="bluetooth.jpg" alt="lanya"></p><center>启用蓝牙支持</center><h3 id="2、启用特定类型蓝牙设备协议支持"><a href="#2、启用特定类型蓝牙设备协议支持" class="headerlink" title="2、启用特定类型蓝牙设备协议支持"></a>2、启用特定类型蓝牙设备协议支持</h3><p>【Bluetooth subsystem support】中有子菜单，按回车进入，如下所示：</p><p><img src= "/img/loading.gif" data-lazy-src="bluetooth2.jpg" alt="lanya2"></p><p>其中有几个选项，控制特定类型蓝牙设备协议的支持，一般全部启用。它们包括：</p><table><thead><tr><th>项目</th><th>说明</th></tr></thead><tbody><tr><td>RFCOMM protocol support</td><td>RFCOMM串口协议，用于设备通信、拨号网络等</td></tr><tr><td>BNET protocol support</td><td>BNEP（Bluetooth Network Encapsulation Protocol，蓝牙网络封装协议），用于蓝牙组建网络，蓝牙上网与组蓝牙个人区域网时需要</td></tr><tr><td>HIDP protocol support</td><td>人体学输入设备，用于连接蓝牙输入设备，如键盘、鼠标</td></tr></tbody></table><h3 id="3、启用蓝牙适配器驱动"><a href="#3、启用蓝牙适配器驱动" class="headerlink" title="3、启用蓝牙适配器驱动"></a>3、启用蓝牙适配器驱动</h3><p>最为重要的一步，就是将蓝牙适配器驱动编译入内核当中。进入最下方子菜单【Bluetooth device drivers】，如下所示：</p><p><img src= "/img/loading.gif" data-lazy-src="bluetooth3.jpg" alt="lanya3"></p><p>菜单中根据接口和特定型号设备，列出了相应的支持选项，有些选项在勾选后还会展开新的选项。典型的接口有USB、SDIO、UART，按需要勾选。<br>笔者X200笔记本的蓝牙适配器是Broadcom BCM2045B，走的是USB通道，因此先勾选【HCI USB driver】，随后会在该项下面出现三个新的选项，再进一步勾选【Broadcom protocol support】。不过，在得知适配器信息之前，笔者拿捏蓝牙适配器可能也走了UART通道，所以也将【HCI UART driver】勾上，再进一步勾选下面的【Intel AG6XX protocol support】。但实际使用时发现，X200的蓝牙适配器的确走的是USB而非UART。若不能确定自己的蓝牙适配器类型，可以一并选上，也不占用太多空间。</p><h3 id="4、重新编译内核"><a href="#4、重新编译内核" class="headerlink" title="4、重新编译内核"></a>4、重新编译内核</h3><p>上述配置完成后，按左右方向键选择”Save“，保存内核配置，然后选”Exit“退出。使用下面的命令重新编译内核并安装：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo make -j2</span><br><span class="line">sudo make modules_install</span><br><span class="line">sudo make install</span><br></pre></td></tr></table></figure><p>重启后，蓝牙功能即被激活。  </p><h3 id="使用体验"><a href="#使用体验" class="headerlink" title="使用体验"></a>使用体验</h3><p>在内核中启用蓝牙支持，并在系统中安装蓝牙组件后，Deepin发生了翻天覆地的变化。Deepin下蓝牙的体验非常出色。<br>Blueman管理器默认开机启动，会在托盘区域出现一个蓝牙图标，在其中可以很方便地管理蓝牙设备。<br>在Blueman管理器中可以搜索到各种蓝牙设备，包括各种手机、电脑，以及笔者的蓝牙耳机。与蓝牙耳机配对后，Deepin即刻将声音通过蓝牙进行播放，无需再进行进一步的配置，尤其方便。此外，Blueman还有其他有趣的玩法，比如文件传输、浏览设备文件，其中对设备文件的浏览功能与当年的MTK功能机类似。</p><p><img src= "/img/loading.gif" data-lazy-src="bluetooth4.jpg" alt="lanya4"></p><p>以X200为代表的ThinkPad早期机型有一项设计非常出彩，就是它屏幕下的灯条，系统运行状态一目了然。其中正包括了蓝牙指示灯，当有数据传输时（如正使用蓝牙音频），指示灯会闪烁，如此就能知道蓝牙设备是否正常工作。可谓匠心。</p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>要想让使用Deepin的笔记本支持蓝牙，需要做两项工作:  </p><ul><li>安装蓝牙组件  </li><li>启用内核的蓝牙支持  </li></ul><p>由此，Deepin下设备的价值就能被进一步挖掘，体验自会更上一层楼。  </p><p>作者：爱拼安小匠<br>链接：<a href="https://www.jianshu.com/p/e5b3f501c953">https://www.jianshu.com/p/e5b3f501c953</a><br>来源：简书<br>简书著作权归作者所有，任何形式的转载都请联系作者获得授权并注明出处。  </p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>deepin系统安装design compiler</title>
      <link href="linux/deepin-designcompiler/"/>
      <url>linux/deepin-designcompiler/</url>
      
        <content type="html"><![CDATA[<h3 id="关于deepin系统安装design-compiler的问题解答"><a href="#关于deepin系统安装design-compiler的问题解答" class="headerlink" title="关于deepin系统安装design compiler的问题解答"></a>关于deepin系统安装design compiler的问题解答</h3><p>Design Compiler是Synopsys综合软件的核心产品。它提供约束驱动时序最优化，并支持众多的设计类型，把设计者的HDL描述综合成与工艺相关的门级设计；它能够从速度、面积和功耗等方面来优化组合电路和时序电路设计，并支持平直或层次化设计.</p><p>然而这个软件是基于Linux系统下面的,所以对于一些不经常接触Linux系统的小伙伴们来说,安装这个软件有一定的难度,尤其是在国产的deepin系统下面安装,网上的教程大多数都是在red hat系统或者是ubuntu的系统下面的  </p><p>本文列出了 安装design compiler可能会遇到的问题的相应解决办法,redhat系统下面的安装可以参考</p><p>secreat data:034f 0000 4db0 0000 2fc0<br>mac:000c29e1c6fa<br>hostname:yanganhan<br>password:</p><p>1.sudo apt-get install yum</p><p>2.开启权限，新建文件<br>  usr/synopsys/pt2016、dc2016、scl、license、installer<br>  其中installer中放入安装文件：pt2016、dc2016、scl、installer3.2<br>  (运行,解压出安装文件：./SynopsysInstaller3.2.run    /usr/syonpsys/installer/installer3.2)<br>  在etc/yum.repos.d/放入.repo源文件</p><p>3.sudo apt-get install -y lsb-base lsb-core</p><p>4.sudo apt-get install lsb</p><p>5.sudo apt-get install csh</p><p>6.安装：./installer   X3——分别安装dc,scl,pt</p><p>7.破解</p><p>8（缺libtiff.so.3）<br>  /usr/lib/i386-linux-gnu/(将libtiff.so.5复制一份改为libtiff.so.3）<br>  sudo ln -s /usr/lib/i386-linux-gnu/libtiff.so.4  /usr/lib/i386-linux-gnu/libtiff.so.3<br>  sudo ln -s /usr/lib/i386-linux-gnu/libtiff.so.5  /usr/lib/i386-linux-gnu/libtiff.so.3</p><p>9（缺libpng12.so.0）sudo apt-get install libpng12-0</p><p>10.lmstat -c /usr/synopsys/license/synopsys.dat<br>  lmgrd -c /usr/synopsys/license/synopsys.dat</p><p>11(备用杀进程license maneger）lmdown -c /usr/synopsys/license/synopsys.dat</p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于安装deepin+window10双系统没有声音的问题</title>
      <link href="linux/deepin-window-audio/"/>
      <url>linux/deepin-window-audio/</url>
      
        <content type="html"><![CDATA[<h3 id="deepin-window10双系统问题"><a href="#deepin-window10双系统问题" class="headerlink" title="deepin+window10双系统问题"></a>deepin+window10双系统问题</h3><p>这个问题小编目前还没有解决,求大神帮忙!<br>deepin社区官网:<a href="https://www.deepin.org/">深度科技社区</a><br>还可以参考一下其他的教程<br>深粉交流:<a href="https://bbs.deepin.org/forum.php?mod=viewthread&tid=39521">新手刚刚安装好DEEPIN，但没有声音，怎而解决？</a><br>冰封飞飞(云网牛站):<a href="https://ywnz.com/linuxjc/3630.html">在Deepin系统中没有声音的解决办法</a><br>冰封飞飞的博客:<a href="https://blog.csdn.net/a363344923/article/details/82955071">deepin系统没有声音的解决方法</a>  </p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> deepin </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JS中的元素获取</title>
      <link href="front/js/js-dom/"/>
      <url>front/js/js-dom/</url>
      
        <content type="html"><![CDATA[<h3 id="常用原生js中的html标签的获取方法"><a href="#常用原生js中的html标签的获取方法" class="headerlink" title="常用原生js中的html标签的获取方法"></a>常用原生js中的html标签的获取方法</h3><table><thead><tr><th>属性/方法</th><th>描述</th></tr></thead><tbody><tr><td>document.getElementsByClassName()</td><td>返回文档中所有指定类名的元素集合，作为 NodeList 对象。</td></tr><tr><td>document.getElementById()</td><td>返回对拥有指定 id 的第一个对象的引用。</td></tr><tr><td>document.getElementsByName()</td><td>返回带有指定名称的对象集合。</td></tr><tr><td>document.getElementsByTagName()</td><td>返回带有指定标签名的对象集合。</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>JS中的定时器</title>
      <link href="front/js/js-interval/"/>
      <url>front/js/js-interval/</url>
      
        <content type="html"><![CDATA[<h3 id="js定时器的制作"><a href="#js定时器的制作" class="headerlink" title="js定时器的制作"></a>js定时器的制作</h3><p>在javascritp中，有两个关于定时器的专用函数，分别为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">1.倒计定时器：timename&#x3D;setTimeout(&quot;function();&quot;,delaytime);  </span><br><span class="line">2.循环定时器：timename&#x3D;setInterval(&quot;function();&quot;,delaytime);</span><br></pre></td></tr></table></figure><p>第一个参数“function()”是定时器触发时要执行的动作，可以是一个函数，也可以是几个函数，函数间用“；”隔开即可。比如要弹出两个警告窗口，便可将“function();”换成<br>“alert(‘第一个警告窗口!’);alert(‘第二个警告窗口!’);”；而第二个参数“delaytime”则是间隔的时间，以毫秒为单位，即填写“5000”，就表示5秒钟。　　</p><p>倒计时定时器是在指定时间到达后触发事件，而循环定时器就是在间隔时间到来时反复触发事件，两者的区别在于：前者只是作用一次，而后者则不停地作用。  </p><p>比如你打开一个页面后，想间隔几秒自动跳转到另一个页面，则你就需要采用倒计定时器“setTimeout(“function();”,delaytime)” ，而如果想将某一句话设置成一个一个字的出现，<br>则需要用到循环定时器“setInterval(“function();”,delaytime)” 。</p><p>获取表单的焦点，则用到document.activeElement.id。利用if来判断document.activeElement.id和表单的ID是否相同。<br>比如：if (“mid” == document.activeElement.id) {alert();},”mid”便是表单对应的ID。</p><p>定时器：<br>用以指定在一段特定的时间后执行某段程序。</p><p>JS中定时执行,setTimeout和setInterval的区别,以及l解除方法</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">setTimeout(Expression,DelayTime),在DelayTime过后,将执行一次Expression,setTimeout 运用在延迟一段时间，再进行某项操作。</span><br><span class="line">setTimeout(&quot;function&quot;,time) 设置一个超时对象</span><br><span class="line"></span><br><span class="line">setInterval(expression,delayTime),每个DelayTime,都将执行Expression.常常可用于刷新表达式.</span><br><span class="line">setInterval(&quot;function&quot;,time) 设置一个超时对象</span><br><span class="line"></span><br><span class="line">SetInterval为自动重复，setTimeout不会重复。</span><br><span class="line"></span><br><span class="line">clearTimeout(对象) 清除已设置的setTimeout对象</span><br><span class="line">clearInterval(对象) 清除已设置的setInterval对象</span><br></pre></td></tr></table></figure><p>##略举两例。</p><h3 id="例1-表单触发或加载时，逐字输出字符串"><a href="#例1-表单触发或加载时，逐字输出字符串" class="headerlink" title="例1.表单触发或加载时，逐字输出字符串"></a>例1.表单触发或加载时，逐字输出字符串</h3><p>代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;Content-Type&quot;</span> <span class="attr">content</span>=<span class="string">&quot;text/html; charset=gb2312&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>无标题文档<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">language</span>=<span class="string">&quot;JavaScript&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> str = <span class="string">&quot;这个是测试用的范例文字&quot;</span>;</span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> seq = <span class="number">0</span>;</span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> second=<span class="number">1000</span>; <span class="comment">//间隔时间1秒钟</span></span></span><br><span class="line"><span class="javascript"><span class="function"><span class="keyword">function</span> <span class="title">scroll</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line">msg = str.substring(0, seq+1);</span><br><span class="line"><span class="javascript"><span class="built_in">document</span>.getElementByIdx_x_x(<span class="string">&#x27;word&#x27;</span>).innerHTML = msg;</span></span><br><span class="line">seq++;</span><br><span class="line">if (seq &gt;= str.length) seq = 0;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span> <span class="attr">onload</span>=<span class="string">&quot;setInterval(&#x27;scroll()&#x27;,second)&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;word&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="例2-当焦点在输入框的时候，定时检查输入框信息，焦点不在时不执行检查动作。"><a href="#例2-当焦点在输入框的时候，定时检查输入框信息，焦点不在时不执行检查动作。" class="headerlink" title="例2.当焦点在输入框的时候，定时检查输入框信息，焦点不在时不执行检查动作。"></a>例2.当焦点在输入框的时候，定时检查输入框信息，焦点不在时不执行检查动作。</h3><p>代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span> <span class="meta-keyword">PUBLIC</span> <span class="meta-string">&quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span> <span class="meta-string">&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.w3.org/1999/xhtml&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;Content-Type&quot;</span> <span class="attr">content</span>=<span class="string">&quot;text/html; charset=gb2312&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>无标题文档<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">language</span>=<span class="string">&quot;JavaScript&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> second=<span class="number">5000</span>; <span class="comment">//间隔时间5秒钟</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> c=<span class="number">0</span>;</span></span><br><span class="line"><span class="javascript"><span class="function"><span class="keyword">function</span> <span class="title">scroll</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line">c++;</span><br><span class="line"><span class="javascript"><span class="keyword">if</span> (<span class="string">&quot;b&quot;</span> == <span class="built_in">document</span>.activeElement.id) &#123;</span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> str=<span class="string">&quot;定时检查第&lt;b&gt; &quot;</span>+c+<span class="string">&quot; &lt;/b&gt;次&lt;br/&gt;&quot;</span>;</span></span><br><span class="line"><span class="javascript"><span class="keyword">if</span>(<span class="built_in">document</span>.getElementByIdx_x_x(<span class="string">&#x27;b&#x27;</span>).value!=<span class="string">&quot;&quot;</span>)&#123;</span></span><br><span class="line"><span class="javascript">str+=<span class="string">&quot;输入框当前内容为当前内容为&lt;br/&gt;&lt;b&gt; &quot;</span>+<span class="built_in">document</span>.getElementByIdx_x_x(<span class="string">&#x27;b&#x27;</span>).value+<span class="string">&quot;&lt;/b&gt;&quot;</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="javascript"><span class="built_in">document</span>.getElementByIdx_x_x(<span class="string">&#x27;word&#x27;</span>).innerHTML = str;</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">textarea</span> <span class="attr">id</span>=<span class="string">&quot;b&quot;</span> <span class="attr">name</span>=<span class="string">&quot;b&quot;</span> <span class="attr">style</span>=<span class="string">&quot;height:100px; width:300px;&quot;</span> <span class="attr">onfocus</span>=<span class="string">&quot;setInterval(&#x27;scroll()&#x27;,second)&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">textarea</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;word&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="例3-下面这个是最简单的例子，定时器时间到达后弹出警告窗口。"><a href="#例3-下面这个是最简单的例子，定时器时间到达后弹出警告窗口。" class="headerlink" title="例3.下面这个是最简单的例子，定时器时间到达后弹出警告窗口。"></a>例3.下面这个是最简单的例子，定时器时间到达后弹出警告窗口。</h3><p>代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.w3.org/1999/xhtml&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;Content-Type&quot;</span> <span class="attr">content</span>=<span class="string">&quot;text/html; charset=gb2312&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">language</span>=<span class="string">&quot;javascript&quot;</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="function"><span class="keyword">function</span> <span class="title">count</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript"><span class="built_in">document</span>.getElementByIdx_x_x(<span class="string">&#x27;m&#x27;</span>).innerHTML=<span class="string">&quot;计时已经开始！&quot;</span>;</span></span><br><span class="line"><span class="javascript"><span class="built_in">setTimeout</span>(<span class="string">&quot;alert(&#x27;十秒钟到！&#x27;)&quot;</span>,<span class="number">10000</span>)</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;m&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">TYPE</span>=<span class="string">&quot;button&quot;</span> <span class="attr">value</span>=<span class="string">&quot; 计时开始&quot;</span> <span class="attr">onclick</span>=<span class="string">&quot;count()&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="例4-倒计时定时跳转"><a href="#例4-倒计时定时跳转" class="headerlink" title="例4:倒计时定时跳转"></a>例4:倒计时定时跳转</h3><p>代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">  &lt;base href&#x3D;&quot;&lt;%&#x3D;basePath%&gt;&quot;&gt;</span><br><span class="line">  &lt;title&gt;My JSP &#39;ds04.jsp&#39; starting page&lt;&#x2F;title&gt;</span><br><span class="line">  &lt;span id&#x3D;&quot;tiao&quot;&gt;3&lt;&#x2F;span&gt;</span><br><span class="line">  &lt;a href&#x3D;&quot;javascript:countDown&quot;&gt; &lt;&#x2F;a&gt;秒后自动跳转……</span><br><span class="line">  &lt;meta http-equiv&#x3D;refresh content&#x3D;3;url&#x3D; &#39;&#x2F;ds02.jsp&#39;&#x2F;&gt;</span><br><span class="line">  &lt;!--脚本开始--&gt;</span><br><span class="line">  &lt;script language&#x3D;&quot;javascript&quot; type&#x3D;&quot;&quot;&gt;</span><br><span class="line">function countDown(secs)&#123;</span><br><span class="line"> tiao.innerText&#x3D;secs;</span><br><span class="line"> if(--secs&gt;0)</span><br><span class="line">  setTimeout(&quot;countDown(&quot;+secs+&quot;)&quot;,1000);</span><br><span class="line"> &#125;</span><br><span class="line"> countDown(3);</span><br><span class="line"> &lt;&#x2F;script&gt;</span><br><span class="line">  &lt;!--脚本结束--&gt;</span><br><span class="line"> &lt;&#x2F;head&gt;</span><br><span class="line"> &lt;&#x2F;html&gt;</span><br></pre></td></tr></table></figure><h3 id="例6"><a href="#例6" class="headerlink" title="例6:"></a>例6:</h3><p>代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;head&gt; </span><br><span class="line">    &lt;meta http-equiv&#x3D;&quot;refresh&quot; content&#x3D;&quot;2;url&#x3D;&#39;b.html&#39;&quot;&gt; </span><br><span class="line">&lt;&#x2F;head&gt; </span><br></pre></td></tr></table></figure><h3 id="例7"><a href="#例7" class="headerlink" title="例7:"></a>例7:</h3><p>代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;script language&#x3D;&quot;javascript&quot; type&#x3D;&quot;text&#x2F;javascript&quot;&gt;</span><br><span class="line"> setTimeout(&quot;window.location.href&#x3D;&#39;b.html&#39;&quot;, 2000);</span><br><span class="line"> &#x2F;&#x2F;下面两个都可以用</span><br><span class="line"> &#x2F;&#x2F;setTimeout(&quot;javascript:location.href&#x3D;&#39;b.html&#39;&quot;, 2000);</span><br><span class="line"> &#x2F;&#x2F;setTimeout(&quot;window.location&#x3D;&#39;b.html&#39;&quot;, 2000);</span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure><h3 id="例8"><a href="#例8" class="headerlink" title="例8:"></a>例8:</h3><p>代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;span id&#x3D;&quot;totalSecond&quot;&gt;2&lt;&#x2F;span&gt;</span><br><span class="line">&lt;script language&#x3D;&quot;javascript&quot; type&#x3D;&quot;text&#x2F;javascript&quot;&gt;</span><br><span class="line"> var second &#x3D; document.getElementByIdx_x(&#39;totalSecond&#39;).innerHTML;</span><br><span class="line"> if(isNaN(second))&#123;</span><br><span class="line">  &#x2F;&#x2F;……不是数字的处理方法</span><br><span class="line"> &#125;else&#123;</span><br><span class="line">  setInterval(function()&#123;</span><br><span class="line">   document.getElementByIdx_x(&#39;totalSecond&#39;).innerHTML &#x3D; --second;</span><br><span class="line">   if (second &lt;&#x3D; 0) &#123;</span><br><span class="line">    window.location &#x3D; &#39;b.html&#39;;</span><br><span class="line">   &#125;</span><br><span class="line">  &#125;, 1000);</span><br><span class="line"> &#125; </span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure><h3 id="js定时器-执行一次、重复执行"><a href="#js定时器-执行一次、重复执行" class="headerlink" title="js定时器(执行一次、重复执行)"></a>js定时器(执行一次、重复执行)</h3><p>分享一段js代码，有关js定时器的小例子，分为执行一次的定时器与重复执行的定时器。供初学的朋友参考。</p><h3 id="1，只执行一次的定时器"><a href="#1，只执行一次的定时器" class="headerlink" title="1，只执行一次的定时器"></a>1，只执行一次的定时器</h3><p>代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span>  </span><br><span class="line"><span class="javascript"><span class="comment">//定时器 异步运行  </span></span></span><br><span class="line"><span class="javascript"><span class="function"><span class="keyword">function</span> <span class="title">hello</span>(<span class="params"></span>)</span>&#123;  </span></span><br><span class="line"><span class="javascript">    alert(<span class="string">&quot;hello&quot;</span>);  </span></span><br><span class="line">&#125;  </span><br><span class="line"><span class="javascript"><span class="comment">//使用方法名字执行方法  </span></span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> t1 = <span class="built_in">window</span>.setTimeout(hello,<span class="number">1000</span>);  </span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> t2 = <span class="built_in">window</span>.setTimeout(<span class="string">&quot;hello()&quot;</span>,<span class="number">3000</span>);<span class="comment">//使用字符串执行方法  </span></span></span><br><span class="line"><span class="javascript"><span class="built_in">window</span>.clearTimeout(t1);<span class="comment">//去掉定时器  </span></span></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="2，重复执行的定时器"><a href="#2，重复执行的定时器" class="headerlink" title="2，重复执行的定时器"></a>2，重复执行的定时器</h3><p>代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span>  </span><br><span class="line"><span class="javascript"><span class="function"><span class="keyword">function</span> <span class="title">hello</span>(<span class="params"></span>)</span>&#123;  </span></span><br><span class="line"><span class="javascript">    alert(<span class="string">&quot;hello&quot;</span>);  </span></span><br><span class="line">&#125;  </span><br><span class="line"><span class="javascript"><span class="comment">//重复执行某个方法  </span></span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> t1 = <span class="built_in">window</span>.setInterval(hello,<span class="number">1000</span>);  </span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> t2 = <span class="built_in">window</span>.setInterval(<span class="string">&quot;hello()&quot;</span>,<span class="number">3000</span>);  </span></span><br><span class="line"><span class="javascript"><span class="comment">//去掉定时器的方法  </span></span></span><br><span class="line"><span class="javascript"><span class="built_in">window</span>.clearInterval(t1);  </span></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>备注：</p><p>如果在一个页面中有两个方法，都是在页面加载完成之后执行的，实际却未能按先后顺序执行，可以参照如下方法解决：<br>可以在onload方法中添加一个定时器，设置一个定时器，“延迟”一段时间之后再运行，即可认为区分页面加载运行方法的先后顺序。</p><p>代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html PUBLIC &quot;-&#x2F;&#x2F;W3C&#x2F;&#x2F;DTD XHTML 1.0 Transitional&#x2F;&#x2F;EN&quot; &quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;xhtml1&#x2F;DTD&#x2F;xhtml1-transitional.dtd&quot;&gt;</span><br><span class="line">&lt;html xmlns&#x3D;&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot;&gt;</span><br><span class="line">&lt;head runat&#x3D;&quot;server&quot;&gt;</span><br><span class="line">    &lt;title&gt;Untitled Page&lt;&#x2F;title&gt;</span><br><span class="line">    &lt;script language&#x3D;&quot;javascript&quot; type&#x3D;&quot;text&#x2F;javascript&quot;&gt;</span><br><span class="line">    var YC &#x3D; new Object();</span><br><span class="line">    function beginYC()</span><br><span class="line">    &#123;</span><br><span class="line">        var secondsYC &#x3D; document.getElementById(&quot;txtYCSeconds&quot;).value;</span><br><span class="line">        try</span><br><span class="line">        &#123; </span><br><span class="line">            YC &#x3D; setTimeout(&quot;alert(&#39;延迟&quot;+secondsYC+&quot;秒成功&#39;)&quot;,secondsYC*1000);</span><br><span class="line">        &#125;</span><br><span class="line">        catch(e)</span><br><span class="line">        &#123;</span><br><span class="line">            alert(&quot;请输入正确的秒数。&quot;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    function overYC()</span><br><span class="line">    &#123;</span><br><span class="line">        clearTimeout(YC);</span><br><span class="line">        YC&#x3D;null;</span><br><span class="line">        alert(&quot;终止延迟成功。&quot;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#x2F;**************************↓↓↓↓定时器的使用↓↓↓↓********************************&#x2F;</span><br><span class="line"></span><br><span class="line">    var timerDS &#x3D; new Object();</span><br><span class="line">    var timerDDS &#x3D; new Object();</span><br><span class="line">    function beginDS()</span><br><span class="line">    &#123;</span><br><span class="line">        sn.innerHTML &#x3D; &quot;0&quot;;</span><br><span class="line">        timerDS &#x3D; setInterval(&quot;addOne()&quot;,parseInt(document.getElementById(&quot;txtIntervalSeconds&quot;).value,10)*1000);</span><br><span class="line">    &#125;</span><br><span class="line">    function goonDS()</span><br><span class="line">    &#123;</span><br><span class="line">        timerDS &#x3D; setInterval(&quot;addOne()&quot;,parseInt(document.getElementById(&quot;txtIntervalSeconds&quot;).value,10)*1000);</span><br><span class="line">    &#125;</span><br><span class="line">    function overDS()</span><br><span class="line">    &#123;</span><br><span class="line">        clearInterval(timerDS);</span><br><span class="line">        timerDS&#x3D;null;</span><br><span class="line">    &#125;</span><br><span class="line">    function delayDS()</span><br><span class="line">    &#123;</span><br><span class="line">        overDS();</span><br><span class="line">        timerDDS &#x3D; setTimeout(&quot;goonDS()&quot;,document.getElementById(&quot;txtDDSSeconds&quot;).value*1000);</span><br><span class="line">    &#125;</span><br><span class="line">    function addOne()</span><br><span class="line">    &#123;</span><br><span class="line">        if(sn.innerHTML&#x3D;&#x3D;&quot;10&quot;)</span><br><span class="line">        &#123;</span><br><span class="line">            overDS();</span><br><span class="line">            alert(&quot;恭喜你，已成功达到10秒&quot;);</span><br><span class="line">            return;</span><br><span class="line">        &#125;</span><br><span class="line">        sn.innerHTML&#x3D;parseInt(sn.innerHTML,10)+1;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &lt;&#x2F;script&gt;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;form id&#x3D;&quot;form1&quot; runat&#x3D;&quot;server&quot;&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        延迟器的使用：&lt;&#x2F;div&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">     &lt;label id&#x3D;&quot;Label2&quot; title&#x3D;&quot;延迟秒数：&quot;&gt;&lt;&#x2F;label&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;text&quot; id&#x3D;&quot;txtYCSeconds&quot; value&#x3D;&quot;3&quot; &#x2F;&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;button&quot; id&#x3D;&quot;btnBYC&quot; onclick&#x3D;&quot;javascript:beginYC()&quot; value&#x3D;&quot;开始延迟&quot; &#x2F;&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;button&quot; id&#x3D;&quot;btnOYC&quot; onclick&#x3D;&quot;javascript:overYC()&quot; value&#x3D;&quot;终止延迟&quot; &#x2F;&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;button&quot; id&#x3D;&quot;Button1&quot; onclick&#x3D;&quot;javascript:alert(&#39;good monrning&#39;);&quot; value&#x3D;&quot;普通弹窗&quot; &#x2F;&gt;</span><br><span class="line">    &lt;&#x2F;div&gt;</span><br><span class="line">    &lt;br &#x2F;&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        定时器的使用：&lt;&#x2F;div&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">    &lt;div id&#x3D;&quot;sn&quot;&gt;0&lt;&#x2F;div&gt;</span><br><span class="line">    &lt;label id&#x3D;&quot;Label1&quot; title&#x3D;&quot;定时间隔秒数：&quot;&gt;&lt;&#x2F;label&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;text&quot; id&#x3D;&quot;txtIntervalSeconds&quot; value&#x3D;&quot;1&quot; &#x2F;&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;button&quot; id&#x3D;&quot;btnBDS&quot; onclick&#x3D;&quot;javascript:beginDS()&quot; value&#x3D;&quot;启动定时&quot; &#x2F;&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;button&quot; id&#x3D;&quot;btnODS&quot; onclick&#x3D;&quot;javascript:overDS()&quot; value&#x3D;&quot;终止定时&quot; &#x2F;&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;button&quot; id&#x3D;&quot;btnGDS&quot; onclick&#x3D;&quot;javascript:goonDS()&quot; value&#x3D;&quot;继续定时&quot; &#x2F;&gt;</span><br><span class="line"></span><br><span class="line">        &lt;label id&#x3D;&quot;ds&quot; title&#x3D;&quot;延迟秒数：&quot;&gt;&lt;&#x2F;label&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;text&quot; id&#x3D;&quot;txtDDSSeconds&quot; value&#x3D;&quot;5&quot; &#x2F;&gt;</span><br><span class="line">        &lt;input type&#x3D;&quot;button&quot; id&#x3D;&quot;btnDDS&quot; onclick&#x3D;&quot;javascript:delayDS()&quot; value&#x3D;&quot;延迟定时&quot; &#x2F;&gt;</span><br><span class="line"></span><br><span class="line">        &lt;&#x2F;div&gt;</span><br><span class="line">    &lt;&#x2F;form&gt;</span><br><span class="line">&lt;&#x2F;body&gt;</span><br><span class="line">&lt;&#x2F;html&gt;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> basis </tag>
            
            <tag> JavaScript </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Node.js笔记整理</title>
      <link href="front/node/nodejs-summary/"/>
      <url>front/node/nodejs-summary/</url>
      
        <content type="html"><![CDATA[<p>是不是在看其他的教程或者文档都比较乏味，本篇文章我们就是随意一点的聊聊node，话不多说，这就开始吧！  </p><h3 id="什么是node-js"><a href="#什么是node-js" class="headerlink" title="什么是node.js"></a>什么是node.js</h3><p>这里跟大家说一下什么是nodejs<br>总结起来三点：  </p><ul><li>编写高性能网络服务器的JavaScript工具包（用js开发服务端程序）</li><li>单线程、异步、事件驱动</li><li>特点：快，耗内存多</li></ul><h3 id="我们先看看PHP的运行机制"><a href="#我们先看看PHP的运行机制" class="headerlink" title="我们先看看PHP的运行机制"></a>我们先看看PHP的运行机制</h3><p>PHP本身不支持多线程，但是比如所它所用的服务器，Apache，它是支持多线程的</p><p>并发的访问服务区，到线程池里取线程<br>这个线程可能会读数据库，上传，或者其他操作，用完线程就恢复，等待其他调用</p><h3 id="现在来看一下node-js的运行机制"><a href="#现在来看一下node-js的运行机制" class="headerlink" title="现在来看一下node.js的运行机制"></a>现在来看一下node.js的运行机制</h3><p>node是单线程的，但是这样会导致效率低，它是通过异步的操作，给你分配一块儿内存，好了，你去操作吧，操作好了在说。<br>就像医院的分诊台，分诊台的护士小姐姐是不管看你的病的哦！<br>这样的优势就是，可以达到百万级的访问量，瞬间就完事儿</p><p>但是他站内存大啊，网上有一个测试，1M的连接量，消耗了16GB的内存（在没有优化的情况下）<br>这内存的问题其实就是用钱来解决的问题就都不是问题了</p><h3 id="PHP面试常见的一个问题："><a href="#PHP面试常见的一个问题：" class="headerlink" title="PHP面试常见的一个问题："></a>PHP面试常见的一个问题：</h3><p>高并发，和大数据量的处理方式，如何优化性能<br>比如优化图片，优化性能，这与node的运行机制是完全不同的</p><p>比如，Java、PHP，在执行5步的时候<br>1<br>2<br>3   的时候去查询数据库去了，查完后回调方法，执行下面的代码<br>4<br>5<br>这就是基于事件的驱动<br>6<br>7<br>要学习node，就要把原来的PHP摒弃掉<br>在nodejs里面，提到了一个async（异步的）流程控制<br>要习惯这种模式 才能学好node  </p><p>行了，写的都是啥啊，正式点了儿┗|｀O′|┛ 嗷~~</p><h3 id="node-js-vs-php"><a href="#node-js-vs-php" class="headerlink" title="node.js vs php"></a>node.js vs php</h3><p>它们其实不是竞争关系，说是互补关系，就凭我这么多年的开发经验，node就是在抢php的饭碗呢。。。</p><p>优点： </p><ul><li><p>性能高，（机制问题）<br>node的性能是真的高，当然的要是php优化好的话，也能跟node比一比吧  </p></li><li><p>开发效率高，（省不少优化的事儿）  </p></li></ul><p>开发效率高，网上有一句话，说一个node程序员能抵得上10个php的程序员，这个当然有点儿夸张了，比如你要是都写一个注册登录页面的话node和php其实是差不了多少的，主要在优化上，就是在大量的高并发，承受大量用户的访问。</p><ul><li>应用范围广（可以开发桌面系统，electron框架）<br>electron对xp系统是不支持的，像socket服务区做的都比php好</li></ul><p>node缺点也有：  </p><ul><li>新、人少，招聘程序员的成本问题</li><li>中间件少<br>php的中间件是非常多的，但是nodejs是几乎没有，你要是做，就要自己写，就也算是新的一个缺点吧</li><li>IDE不完善<br>集成开发环境能够影响开发的效率吧<br>自动生成代码工具，没有几个<br>就有个orm</li></ul><h3 id="node-js-的劣势和解决方案（总之就是没有缺点）"><a href="#node-js-的劣势和解决方案（总之就是没有缺点）" class="headerlink" title="node.js 的劣势和解决方案（总之就是没有缺点）"></a>node.js 的劣势和解决方案（总之就是没有缺点）</h3><ul><li>默认不支持多核，但是cluster可以解决    </li><li>默认不支持服务器集群，node-http-proxy可以解决    </li><li>使用nginx做负载均衡，静态的有nginx处理，动态的有node.js处理  </li><li>forever或者node-cluster实现灾难恢复  </li></ul><h3 id="学习的框架给你推荐，拿走不谢！"><a href="#学习的框架给你推荐，拿走不谢！" class="headerlink" title="学习的框架给你推荐，拿走不谢！"></a>学习的框架给你推荐，拿走不谢！</h3><ul><li>比较热门的包括： express、koa、Hapi</li><li>以及express基础之上的sails</li><li>express：完善、稳定、文档全、社区大</li><li>koa：超前，正在完善中</li><li>Hapi：复杂（一个简单的helloworld，到要做很多堆彻），<br>适合复杂的大型项目  </li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python自然语言处理工具小结</title>
      <link href="python/collection/python-language/"/>
      <url>python/collection/python-language/</url>
      
        <content type="html"><![CDATA[<h3 id="Python-的几个自然语言处理工具"><a href="#Python-的几个自然语言处理工具" class="headerlink" title="Python 的几个自然语言处理工具"></a>Python 的几个自然语言处理工具</h3><ul><li><p>NLTK:NLTK 在用 Python 处理自然语言的工具中处于领先的地位。它提供了 WordNet 这种方便处理词汇资源的借口，还有分类、分词、除茎、标注、语法分析、语义推理等类库。</p></li><li><p>Pattern:Pattern 的自然语言处理工具有词性标注工具(Part-Of-Speech Tagger)，N元搜索(n-gram search)，情感分析(sentiment analysis)，WordNet。支持机器学习的向量空间模型，聚类，向量机。</p></li><li><p>TextBlob:TextBlob 是一个处理文本数据的 Python 库。提供了一些简单的api解决一些自然语言处理的任务，例如词性标注、名词短语抽取、情感分析、分类、翻译等等。</p></li><li><p>Gensim:Gensim 提供了对大型语料库的主题建模、文件索引、相似度检索的功能。它可以处理大于RAM内存的数据。作者说它是“实现无干预从纯文本语义建模的最强大、最高效、最无障碍的软件。</p></li><li><p>PyNLPI:它的全称是：Python自然语言处理库（Python Natural Language Processing Library，音发作: pineapple） 这是一个各种自然语言处理任务的集合，PyNLPI可以用来处理N元搜索，计算频率表和分布，建立语言模型。他还可以处理向优先队列这种更加复杂的数据结构，或者像 Beam 搜索这种更加复杂的算法。</p></li><li><p>spaCy:这是一个商业的开源软件。结合Python和Cython，它的自然语言处理能力达到了工业强度。是速度最快，领域内最先进的自然语言处理工具。</p></li><li><p>Polyglot:Polyglot 支持对海量文本和多语言的处理。它支持对165种语言的分词，对196中语言的辨识，40种语言的专有名词识别，16种语言的词性标注，136种语言的情感分析，137种语言的嵌入，135种语言的形态分析，以及69中语言的翻译。</p></li><li><p>MontyLingua:MontyLingua 是一个自由的、训练有素的、端到端的英文处理工具。输入原始英文文本到 MontyLingua ，就会得到这段文本的语义解释。适合用来进行信息检索和提取，问题处理，回答问题等任务。从英文文本中，它能提取出主动宾元组，形容词、名词和动词短语，人名、地名、事件，日期和时间，等语义信息。</p></li><li><p>BLLIP Parser:BLLIP Parser（也叫做Charniak-Johnson parser）是一个集成了产生成分分析和最大熵排序的统计自然语言工具。包括 命令行 和 python接口 。</p></li><li><p>Quepy:Quepy是一个Python框架，提供将自然语言转换成为数据库查询语言。可以轻松地实现不同类型的自然语言和数据库查询语言的转化。所以，通过Quepy，仅仅修改几行代码，就可以实现你自己的自然语言查询数据库系统。GitHub:<a href="https://github.com/machinalis/quepy">https://github.com/machinalis/quepy</a></p></li><li><p>HanNLP：HanLP是由一系列模型与算法组成的Java工具包，目标是普及自然语言处理在生产环境中的应用。不仅仅是分词，而是提供词法分析、句法分析、语义理解等完备的功能。HanLP具备功能完善、性能高效、架构清晰、语料时新、可自定义的特点。文档使用操作说明：Python调用自然语言处理包HanLP 和 菜鸟如何调用HanNLP</p></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>linux中的技巧和快捷键总结</title>
      <link href="linux/linux-skills/"/>
      <url>linux/linux-skills/</url>
      
        <content type="html"><![CDATA[<section class="" mpa-from-tpl="t">    <section mpa-from-tpl="t">        <section class="" style="" powered-by="xiumi.us" mpa-from-tpl="t">            <section style="margin: 10px 0% 8px;" mpa-from-tpl="t">                <section                        style="display: inline-block;width: 100%;vertical-align: top;border-left: 3px solid rgb(160, 160, 160);border-bottom-left-radius: 0px;padding-left: 8px;background-color: rgb(250, 250, 250);"                        mpa-from-tpl="t">                    <section class="" powered-by="xiumi.us" mpa-from-tpl="t">                        <section style="" mpa-from-tpl="t">                            <section style="color: rgb(123, 123, 123);" mpa-from-tpl="t"><p><span                                    style="font-size: 14px;"></span></p></section>                        </section>                    </section>                </section>            </section>        </section>    </section></section><h2 style="color: inherit;line-height: inherit;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;margin-top: 5px;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">前言</span><br></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    linux中的一些小技巧可以大大提高你的工作效率，本文就细数那些提高效率或者简单却有效的linux技巧。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">命令编辑及光标移动</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    这里有很多快捷键可以帮我们修正自己的命令。接下来使用光标二字代替光标的位置。</p><h4        style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">删除从开头到光标处的命令文本</span></h4><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">ctrl +    u，例如：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">$ cd</span>&nbsp;/proc/tty;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">ls</span>&nbsp;-al光标<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">如果此时使用ctrl    + u快捷键，那么该条命令都会被清除，而不需要长按backspace键。</p><h4        style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">删除从光标到结尾处的命令文本</span></h4><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    ctrl+k，例如：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">$ cd</span>&nbsp;/proc/tty光标;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">ls</span>&nbsp;-al<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">如果此时使用ctrl    + k快捷键，那么从光标开始处到结尾的命令文本将会被删除。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    还有其他的操作，不再举例，例如：</p><ul style="" class="list-paddingleft-2">    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">ctrl + a:光标移动到命令开头</span></p></li>    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">ctrl + e：光标移动到命令结尾</span></p></li>    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">alt &nbsp;f:光标向前移动一个单词</span></p>    </li>    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">alt &nbsp;b：光标向前移动一个单词</span></p>    </li>    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">ctrl w：删除一个词（以空格隔开的字符串）</span></p>    </li></ul><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">历史命令快速执行</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    我们都知道history记录了执行的历史命令，而使用!＋历史命令前的数字，可快速执行历史命令。另外，还可以使用ctrl+r搜索执行过的命令。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">部分历史命令查看</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    history会显示大量的历史命令，而fs -l只会显示部分。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">实时查看日志</span></h2><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;tail&nbsp;-f&nbsp;filename.<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">log</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">tail -f    加文件名，可以实时显示日志文件内容。当然，使用less命令查看文件内容，并且使用shift+f键，也可达到类似的效果。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">磁盘或内存情况查看</span></h2><h4        style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">怎么知道当前磁盘是否满了呢？</span></h4><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;df&nbsp;-h<br>/dev/sda14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">4.6</span>G&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">10</span>M&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">4.4</span>G&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>%&nbsp;/tmp<br>/dev/sda11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">454</span>M&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">366</span>M&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">61</span>M&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">86</span>%&nbsp;/boot<br>/dev/sda15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">55</span>G&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">18</span>G&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">35</span>G&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">35</span>%&nbsp;/home<br>/dev/sda1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">256</span>M&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">31</span>M&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">226</span>M&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">12</span>%&nbsp;/boot/efi<br>tmpfs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">786</span>M&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">64</span>K&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">786</span>M&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>%&nbsp;/run/user/<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1000</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    使用df命令可以快速查看各挂载路径磁盘占用情况。</p><h4        style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">当前目录各个子目录占用空间大小</span></h4><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    如果你已经知道home目录占用空间较大了，你想知道home目录下各个目录占用情况：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;du&nbsp;-h&nbsp;–-max-depth=<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>&nbsp;/home(或者-d&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>)<br><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">18</span>G&nbsp;&nbsp;&nbsp;&nbsp;/home/hyb<br><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">16</span>K&nbsp;&nbsp;&nbsp;&nbsp;/home/lost+found<br><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">18</span>G&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">/home/</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    这里指定了目录深度，否则的话，它会递归统计子目录占用空间大小，可自行尝试。</p><h4        style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">当前内存使用情况</span></h4><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">free</span>&nbsp;-h<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;total&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;used&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">free</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shared&nbsp;&nbsp;buff/cache&nbsp;&nbsp;&nbsp;available<br>Mem:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">7.7</span>G&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">3.5</span>G&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">452</span>M&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">345</span>M&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">3.7</span>G&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">3.5</span>G<br>Swap:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">7.6</span>G&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">0B</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">7.6</span>G<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    通过free的结果，很容易看到当前总共内存多少，剩余可用内存多少等等。</p><h4        style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">使用-h参数</span></h4><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    不知道你是否注意到，我们在前面几个命令中，都使用了-h参数，它的作用是使得结果以人类可读的方式呈现，所以我们看到它呈现的单位是G,M等，如果不使用-h参数，可以自己尝试一下会是什么样的结果呈现。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">根据名称查找进程id</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    想快速直接查找进程id，可以使用：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;pgrep&nbsp;hello<br><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">22692</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">或者：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;pidof&nbsp;hello<br><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">22692</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    其中，hello是进程名称。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">根据名称杀死进程</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    一般我们可以使用kill　-9 pid方式杀死一个进程，但是这样就需要先找到这个进程的进程id，实际上我们也可以直接根据名称杀死进程，例如：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;killall&nbsp;hello<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">或者：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">$ pkill</span>&nbsp;hello<br></code></pre><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">查看进程运行时间</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    可以使用下面的命令查看进程已运行时间：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;ps&nbsp;-p&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">24525</span>&nbsp;-o&nbsp;lstart,etime&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STARTED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ELAPSED<br>Sat&nbsp;Mar&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">23</span>&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">20</span>:<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">52</span>:<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">08</span>&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">2019</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">02</span>:<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">45</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    其中24525是你要查看进程的进程id。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">快速目录切换</span></h2><ul style="" class="list-paddingleft-2">    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">cd -　回到上一个目录</span></p></li>    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">cd &nbsp;回到用户家目录</span></p></li></ul><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">多条命令执行</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    我们知道使用分号隔开可以执行多条命令，例如：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);word-wrap: inherit !important;word-break: inherit !important;">$</span><span        class=""        style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">cd</span>&nbsp;/temp/<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">log</span>/;rm&nbsp;-rf&nbsp;*</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    但是如果当前目录是/目录，并且/temp/log目录不存在，那么就会发生激动人心的一幕：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">bash:&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">cd</span>:&nbsp;/temp/<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">log</span>:&nbsp;No&nbsp;such&nbsp;file&nbsp;or&nbsp;directory<br>（突然陷入沉默）<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    因为;可以执行多条命令，但是不会因为前一条命令失败，而导致后面的不会执行，因此，cd执行失败后，仍然会继续执行rm -rf *，由于处于/目录下，结果可想而知。<br>所以你还以为这种事故是对rf -rf    *的力量一无所知的情况下产生的吗？</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    如果解决呢？很简单，使用&amp;&amp;，例如:</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);word-wrap: inherit !important;word-break: inherit !important;">$</span><span        class=""        style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">cd</span>&nbsp;/temp/<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">log</span>/&amp;&amp;rm&nbsp;-rf&nbsp;*</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    这样就会确保前一条命令执行成功，才会执行后面一条。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">查看压缩日志文件</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    有时候日志文件是压缩的，那么能不能偷懒一下，不解压查看呢？当然可以啦。<br>例如：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;zcat&nbsp;test.gz<br><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">test</span>&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">log</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">或者：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;zless&nbsp;test.gz<br><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">test</span>&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">log</span></code></pre><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">清空文件内容</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    比如有一个大文件，你想快速删除，或者不想删除，但是想清空内容：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);word-wrap: inherit !important;word-break: inherit !important;">&gt;</span><span        class=""        style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">filename</span><br></code></pre><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">将日志同时记录文件并打印到控制台</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    在执行shell脚本，常常会将日志重定向，但是这样的话，控制台就没有打印了，如何使得既能记录日志文件，又能将日志输出到控制台呢？</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;./test.sh&nbsp;|tee&nbsp;test.<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">log</span><br></code></pre><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">终止并恢复进程执行</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">我们使用ctrl+z    暂停一个进程的执行，也可以使用fg恢复执行。例如我们使用</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;cat&nbsp;filename<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    当我们发现文件内容可能很多时，使用ctrl+z暂停程序，而如果又想要从刚才的地方继续执行，则只需要使用fg命令即可恢复执行。或者使用bg使得进程继续在后台执行。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">计算程序运行时间</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    我们可能会进程写一些小程序，并且想要知道它的运行时间，实际上我们可以很好的利用time命令帮我们计算，例如：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;time&nbsp;./fibo&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">30</span><br>the&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">30</span>&nbsp;result&nbsp;is&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">832040</span><br><br><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">real</span>&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">0</span>m0<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">.088s</span><br>user&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">0</span>m0<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">.084s</span><br>sys&nbsp;&nbsp;&nbsp;&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">0</span>m0<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">.004s</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    它会显示系统时间，用户时间以及实际使用的总时间。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">查看内存占用前10的进程</span></h2><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">$ ps</span>&nbsp;-aux|sort&nbsp;-k4nr&nbsp;|head&nbsp;-n&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">10</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    这里综合使用了ps，sort，head命令。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">快速查找你需要的命令</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    我们都知道man可以查看命令的帮助手册，但是如果我们想要某个功能却不知道使用哪个命令呢？别着急，还是可以使用man：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;man&nbsp;-k&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"copy&nbsp;files"</span><br>cp&nbsp;(<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;copy&nbsp;files&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">and</span>&nbsp;directories<br>cpio&nbsp;(<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;copy&nbsp;files&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">to</span>&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">and</span>&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">from</span>&nbsp;archives<br>git-checkout-index&nbsp;(<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>)&nbsp;-&nbsp;Copy&nbsp;files&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">from</span>&nbsp;the&nbsp;index&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">to</span>&nbsp;the&nbsp;working&nbsp;tree<br>gvfs-copy&nbsp;(<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;Copy&nbsp;files<br>gvfs-move&nbsp;(<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;Copy&nbsp;files<br>install&nbsp;(<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;copy&nbsp;files&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">and</span>&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">set</span>&nbsp;attributes<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    使用-k参数，使得与copy files相关的帮助手册都显示出来了。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">命令行下的复制粘贴</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    我们知道，在命令行下，复制不能再是ctrl + c了，因为它表示终止当前进程，而控制台下的复制粘贴需要使用下面的快捷键：</p><ul style="" class="list-paddingleft-2">    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">ctrl + &nbsp;insert</span></p></li>    <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">shift + insert</span></p></li></ul><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">搜索包含某个字符串的文件</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    例如，要在当前目录下查找包含test字符串的文件：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;grep&nbsp;-rn&nbsp;<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"test"</span><br>test2.<span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">txt:</span><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">:test</span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    它便可以找到该字符串在哪个文件的第几行。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">屏幕冻结</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    程序运行时，终端可能输出大量的日志，你想简单查看一下，又不想记录日志文件，此时可以使用ctrl+s键，冻结屏幕，使得日志不再继续输出，而如果想要恢复，可使用ctrl+q退出冻结。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">无编辑器情况下编辑文本文件</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    如果在某些系统上连基本的vi编辑器都没有，那么可以使用下面的方式进行编辑内容：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;cat&nbsp;&gt;file.txt<br>some&nbsp;words<br>(ctrl+d)<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    编辑完成后，ctrl+d即可保存。</p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">查看elf文件</span></h2><h4        style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">查看elf文件头信息</span></h4><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">例如：</p><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$&nbsp;readelf&nbsp;-h&nbsp;filename<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    我们在显示结果中，可以看到运行的平台，elf文件类型，大小端情况等。</p><h4        style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">查看库中是否包含某个接口</span></h4><pre style="font-size: inherit;color: inherit;line-height: inherit;"><code class=""                                                                           style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">$ nm&nbsp;filename&nbsp;|grep&nbsp;<span        class=""        style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><span        class=""        style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">interface</span></span><br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    这里是从文件filename中查看是否包含interface接口，前提是该文件包含符号表。<br></p><h2 style="color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;">    <span style="font-size: inherit;color: inherit;line-height: inherit;">总结</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">    本文所提到的内容建议自己上机操作，体验效果。本文总结了一些常用的linux小技巧，你还有哪些linux小技巧？欢迎留言分享。</p><section class="" mpa-from-tpl="t"><p><br></p>    <section class="" mpa-from-tpl="t" style="color: rgb(51, 51, 51);font-size: 17px;text-align: justify;"><p style="clear: both;min-height: 1em;"><br mpa-from-tpl="t"></p></section>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>思维导图简识</title>
      <link href="linux/xmind/"/>
      <url>linux/xmind/</url>
      
        <content type="html"><![CDATA[<h3 id="表达发散性思维的有效图形思维工具-思维导图"><a href="#表达发散性思维的有效图形思维工具-思维导图" class="headerlink" title="表达发散性思维的有效图形思维工具-思维导图"></a>表达发散性思维的有效图形思维工具-思维导图</h3><p>思维导图，英文是The Mind Map，又叫心智导图，是表达发散性思维的有效图形思维工具 ，它简单却又很有效，是一种实用性的思维工具。</p><p>思维导图运用图文并重的技巧，把各级主题的关系用相互隶属与相关的层级图表现出来，把主题关键词与图像、颜色等建立记忆链接。思维导图充分运用左右脑的机能，利用记忆、阅读、思维的规律，协助人们在科学与艺术、逻辑与想象之间平衡发展，从而开启人类大脑的无限潜能。思维导图因此具有人类思维的强大功能。</p><p>思维导图是一种将思维形象化的方法。我们知道放射性思考是人类大脑的自然思考方式，每一种进入大脑的资料，不论是感觉、记忆或是想法——包括文字、数字、符码、香气、食物、线条、颜色、意象、节奏、音符等，都可以成为一个思考中心，并由此中心向外发散出成千上万的关节点，每一个关节点代表与中心主题的一个连结，而每一个连结又可以成为另一个中心主题，再向外发散出成千上万的关节点，呈现出放射性立体结构，而这些关节的连结可以视为您的记忆，就如同大脑中的神经元一样互相连接，也就是您的个人数据库。</p><p>思维导图又称脑图、心智地图、脑力激荡图、灵感触发图、概念地图、树状图、树枝图或思维地图，是一种图像式思维的工具以及一种利用图像式思考辅助工具。思维导图是使用一个中央关键词或想法引起形象化的构造和分类的想法；它用一个中央关键词或想法以辐射线形连接所有的代表字词、想法、任务或其它关联项目的图解方式。</p><h3 id="以特定的图形符号加上说明，表示算法的图-流程图"><a href="#以特定的图形符号加上说明，表示算法的图-流程图" class="headerlink" title="以特定的图形符号加上说明，表示算法的图-流程图"></a>以特定的图形符号加上说明，表示算法的图-流程图</h3><p>流程图是流经一个系统的信息流、观点流或部件流的图形代表。在企业中，流程图主要用来说明某一过程。这种过程既可以是生产线上的工艺流程，也可以是完成一项任务必需的管理过程。</p><p>例如，一张流程图能够成为解释某个零件的制造工序，甚至组织决策制定程序的方式之一。这些过程的各个阶段均用图形块表示，不同图形块之间以箭头相连，代表它们在系统内的流动方向。下一步何去何从，要取决于上一步的结果，典型做法是用“是”或“否”的逻辑分支加以判断。</p><p>流程图是揭示和掌握封闭系统运动状况的有效方式。作为诊断工具，它能够辅助决策制定，让管理者清楚地知道，问题可能出在什么地方，从而确定出可供选择的行动方案。</p><p>流程图有时也称作输入-输出图。该图直观地描述一个工作过程的具体步骤。流程图对准确了解事情是如何进行的，以及决定应如何改进过程极有帮助。这一方法可以用于整个企业，以便直观地跟踪和图解企业的运作方式。</p><p>流程图使用一些标准符号代表某些类型的动作，如决策用菱形框表示，具体活动用方框表示。但比这些符号规定更重要的，是必须清楚地描述工作过程的顺序。流程图也可用于设计改进工作过程，具体做法是先画出事情应该怎么做，再将其与实际情况进行比较。</p><h3 id="在线制作思维导图和流程图工具"><a href="#在线制作思维导图和流程图工具" class="headerlink" title="在线制作思维导图和流程图工具"></a>在线制作思维导图和流程图工具</h3><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/xmind/xmind.jpg" alt="各个国家流程图对比"><br><a href="https://www.processon.com/">process官网</a></p><p><a href="https://www.edrawsoft.cn/">mindmaster官网</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> basis </tag>
            
            <tag> skills </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>nodejs简介</title>
      <link href="front/node/node-introduce/"/>
      <url>front/node/node-introduce/</url>
      
        <content type="html"><![CDATA[<h3 id="nodejs是啥？"><a href="#nodejs是啥？" class="headerlink" title="nodejs是啥？"></a>nodejs是啥？</h3><ul><li><p>Node.js是运行在服务端的JavaScript。</p></li><li><p>Node.js是一个基于Chrome JavaScript运行时建立的一个平台。</p></li><li><p>Node.js是一个事件驱动I/O服务端JavaScript环境，基于Google的V8引擎，V8引擎执行Javascript的速度非常快，性能非常好。</p></li></ul><h3 id="Node-js适合哪些人来使用呢？"><a href="#Node-js适合哪些人来使用呢？" class="headerlink" title="Node.js适合哪些人来使用呢？"></a>Node.js适合哪些人来使用呢？</h3><ul><li><p>对于不会运用Python、PHP以及Java等动态编程语言的前端程序员来说，选择Node.js作为一个创建自己的服务的工具是非常明智的。</p></li><li><p>Node.js是运行在服务端的JavaScript，因此，熟悉Javascript的使用将有助于学习Node.js。</p></li><li><p>同时，学习该Node.js教程也可以帮助后端程序员部署一些高性能的服务。</p></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Node.js中的回调函数</title>
      <link href="front/node/nodejs-callback-function/"/>
      <url>front/node/nodejs-callback-function/</url>
      
        <content type="html"><![CDATA[<h3 id="Node-js-回调函数"><a href="#Node-js-回调函数" class="headerlink" title="Node.js 回调函数"></a>Node.js 回调函数</h3><p>Node.js 异步编程的直接体现就是回调。</p><p>异步编程依托于回调来实现，但不能说使用了回调后程序就异步化了。</p><p>回调函数在完成任务后就会被调用，Node 使用了大量的回调函数，Node 所有 API 都支持回调函数。</p><p>例如，我们可以一边读取文件，一边执行其他命令，在文件读取完成后，我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能，可以处理大量的并发请求。</p><h3 id="阻塞代码实例"><a href="#阻塞代码实例" class="headerlink" title="阻塞代码实例"></a>阻塞代码实例</h3><p>创建一个文件 xiaoming.txt ，内容如下：<br><code>小明的博客的首页地址 » https://victorfengming.gitee.io/#blog </code><br>创建 main.js 文件, 代码如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">var fs &#x3D; require(&quot;fs&quot;);</span><br><span class="line"></span><br><span class="line">var data &#x3D; fs.readFileSync(&#39;xiaoming.txt&#39;);</span><br><span class="line"></span><br><span class="line">console.log(data.toString());</span><br><span class="line">console.log(&quot;程序执行结束!&quot;);</span><br></pre></td></tr></table></figure><p>以上代码执行结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ node main.js</span><br><span class="line">小明的博客的首页地址 » https:&#x2F;&#x2F;victorfengming.gitee.io&#x2F;#blog </span><br><span class="line"></span><br><span class="line">程序执行结束!</span><br></pre></td></tr></table></figure><h3 id="非阻塞代码实例"><a href="#非阻塞代码实例" class="headerlink" title="非阻塞代码实例"></a>非阻塞代码实例</h3><p>创建一个文件 xiaoming.txt ，内容如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">小明的博客的首页地址 » https:&#x2F;&#x2F;victorfengming.gitee.io&#x2F;#blog </span><br></pre></td></tr></table></figure><p>创建 main.js 文件, 代码如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">var fs &#x3D; require(&quot;fs&quot;);</span><br><span class="line"></span><br><span class="line">fs.readFile(&#39;xiaoming.txt&#39;, function (err, data) &#123;</span><br><span class="line">    if (err) return console.error(err);</span><br><span class="line">    console.log(data.toString());</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">console.log(&quot;程序执行结束!&quot;);</span><br></pre></td></tr></table></figure><p>以上代码执行结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ node main.js</span><br><span class="line">程序执行结束!</span><br><span class="line">小明的博客的首页地址 » https:&#x2F;&#x2F;victorfengming.gitee.io&#x2F;#blog </span><br></pre></td></tr></table></figure><h3 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h3><p>以上两个实例我们了解了阻塞与非阻塞调用的不同。第一个实例在文件读取完后才执行完程序。 第二个实例我们呢不需要等待文件读取完，这样就可以在读取文件时同时执行接下来的代码，大大提高了程序的性能。</p><p>因此，阻塞按是按顺序执行的，而非阻塞是不需要按顺序的，所以如果需要处理回调函数的参数，我们就需要写在回调函数内。</p>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Node.js中事件的循环</title>
      <link href="front/node/nodejs-event-loop/"/>
      <url>front/node/nodejs-event-loop/</url>
      
        <content type="html"><![CDATA[<h3 id="Node-js-事件循环"><a href="#Node-js-事件循环" class="headerlink" title="Node.js 事件循环"></a>Node.js 事件循环</h3><p>Node.js 是单进程单线程应用程序，但是通过事件和回调支持并发，所以性能非常高。</p><p>Node.js 的每一个 API 都是异步的，并作为一个独立线程运行，使用异步函数调用，并处理并发。</p><p>Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。</p><p>Node.js 单线程类似进入一个while(true)的事件循环，直到没有事件观察者退出，每个异步事件都生成一个事件观察者，如果有事件发生就调用该回调函数.</p><h3 id="事件驱动程序"><a href="#事件驱动程序" class="headerlink" title="事件驱动程序"></a>事件驱动程序</h3><p>Node.js 使用事件驱动模型，当web server接收到请求，就把它关闭然后进行处理，然后去服务下一个web请求。</p><p>当这个请求完成，它被放回处理队列，当到达队列开头，这个结果被返回给用户。</p><p>这个模型非常高效可扩展性非常强，因为webserver一直接受请求而不等待任何读写操作。（这也被称之为非阻塞式IO或者事件驱动IO）</p><p>在事件驱动模型中，会生成一个主循环来监听事件，当检测到事件时触发回调函数。<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/node/event_loop.jpg" alt="event loop"></p><p>整个事件驱动的流程就是这么实现的，非常简洁。有点类似于观察者模式，事件相当于一个主题(Subject)，而所有注册到这个事件上的处理函数相当于观察者(Observer)。</p><p>Node.js 有多个内置的事件，我们可以通过引入 events 模块，并通过实例化 EventEmitter 类来绑定和监听事件，如下实例：  </p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 引入 events 模块</span></span><br><span class="line"><span class="keyword">var</span> events = <span class="built_in">require</span>(<span class="string">&#x27;events&#x27;</span>);</span><br><span class="line"><span class="comment">// 创建 eventEmitter 对象</span></span><br><span class="line"><span class="keyword">var</span> eventEmitter = <span class="keyword">new</span> events.EventEmitter();</span><br></pre></td></tr></table></figure><p>以下程序绑定事件处理程序：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 绑定事件及事件的处理程序</span></span><br><span class="line">eventEmitter.on(<span class="string">&#x27;eventName&#x27;</span>, eventHandler);</span><br></pre></td></tr></table></figure><p>我们可以通过程序触发事件：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 触发事件</span></span><br><span class="line">eventEmitter.emit(<span class="string">&#x27;eventName&#x27;</span>);</span><br></pre></td></tr></table></figure><h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><p>创建 main.js 文件，代码如下所示：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 引入 events 模块</span></span><br><span class="line"><span class="keyword">var</span> events = <span class="built_in">require</span>(<span class="string">&#x27;events&#x27;</span>);</span><br><span class="line"><span class="comment">// 创建 eventEmitter 对象</span></span><br><span class="line"><span class="keyword">var</span> eventEmitter = <span class="keyword">new</span> events.EventEmitter();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建事件处理程序</span></span><br><span class="line"><span class="keyword">var</span> connectHandler = <span class="function"><span class="keyword">function</span> <span class="title">connected</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">&#x27;连接成功。&#x27;</span>);</span><br><span class="line">  </span><br><span class="line">   <span class="comment">// 触发 data_received 事件 </span></span><br><span class="line">   eventEmitter.emit(<span class="string">&#x27;data_received&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 绑定 connection 事件处理程序</span></span><br><span class="line">eventEmitter.on(<span class="string">&#x27;connection&#x27;</span>, connectHandler);</span><br><span class="line"> </span><br><span class="line"><span class="comment">// 使用匿名函数绑定 data_received 事件</span></span><br><span class="line">eventEmitter.on(<span class="string">&#x27;data_received&#x27;</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">&#x27;数据接收成功。&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 触发 connection 事件 </span></span><br><span class="line">eventEmitter.emit(<span class="string">&#x27;connection&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;程序执行完毕。&quot;</span>);</span><br></pre></td></tr></table></figure><p>接下来让我们执行以上代码：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ node main.js</span><br><span class="line">连接成功。</span><br><span class="line">数据接收成功。</span><br><span class="line">程序执行完毕。</span><br></pre></td></tr></table></figure><h3 id="Node-应用程序是如何工作的？"><a href="#Node-应用程序是如何工作的？" class="headerlink" title="Node 应用程序是如何工作的？"></a>Node 应用程序是如何工作的？</h3><p>在 Node 应用程序中，执行异步操作的函数将回调函数作为最后一个参数， 回调函数接收错误对象作为第一个参数。</p><p>接下来让我们来重新看下前面的实例，创建一个 demo.txt ,文件内容如下：</p><p><code>小明的博客的首页地址 » https://victorfengming.gitee.io/#blog </code></p><p>创建 main.js 文件，代码如下：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> fs = <span class="built_in">require</span>(<span class="string">&quot;fs&quot;</span>);</span><br><span class="line"></span><br><span class="line">fs.readFile(<span class="string">&#x27;demo.txt&#x27;</span>, <span class="function"><span class="keyword">function</span> (<span class="params">err, data</span>) </span>&#123;</span><br><span class="line">   <span class="keyword">if</span> (err)&#123;</span><br><span class="line">      <span class="built_in">console</span>.log(err.stack);</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="built_in">console</span>.log(data.toString());</span><br><span class="line">&#125;);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;程序执行完毕&quot;</span>);</span><br></pre></td></tr></table></figure><p>以上程序中 fs.readFile() 是异步函数用于读取文件。 如果在读取文件过程中发生错误，错误 err 对象就会输出错误信息。</p><p>如果没发生错误，readFile 跳过 err 对象的输出，文件内容就通过回调函数输出。</p><p>执行以上代码，执行结果如下：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">程序执行完毕</span><br><span class="line">小明的博客的首页地址 » https:<span class="comment">//victorfengming.gitee.io/#blog </span></span><br></pre></td></tr></table></figure><p>接下来我们删除 demo.txt 文件，执行结果如下所示：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">程序执行完毕</span><br><span class="line"><span class="built_in">Error</span>: ENOENT, open <span class="string">&#x27;demo.txt&#x27;</span></span><br></pre></td></tr></table></figure><p>因为文件 demo.txt 不存在，所以输出了错误信息。</p>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>node的第一个程序</title>
      <link href="front/node/nodejs-helloworld/"/>
      <url>front/node/nodejs-helloworld/</url>
      
        <content type="html"><![CDATA[<h3 id="helloworld"><a href="#helloworld" class="headerlink" title="helloworld"></a>helloworld</h3><p>首先你要保证你的环境中已经安装好node了，关于node的安装可以参考<a href="https://victorfengming.gitee.io/blog/nodejs-install/">ubuntu系统下nodejs的安装</a><br>第一个Node.js程序：Hello World！</p><h3 id="脚本模式-写入js文件"><a href="#脚本模式-写入js文件" class="headerlink" title="脚本模式(写入js文件)"></a>脚本模式(写入js文件)</h3><p>以下是我们的第一个Node.js程序：<br>新建一个扩展名为js的文件，添加内容如下<br><code>console.log(&quot;Hello World&quot;);</code><br>保存该文件，文件名为helloworld.js<br>切换到该文件的目录，并通过node命令来执行：<br><code>node helloworld.js</code><br>程序执行后，正常的话，就会在终端输出<code>Hello World</code>。</p><h3 id="交互模式-命令行"><a href="#交互模式-命令行" class="headerlink" title="交互模式(命令行)"></a>交互模式(命令行)</h3><p>打开终端，键入node进入命令交互模式，可以输入一条代码语句后立即执行并显示结果，例如：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ node</span><br><span class="line">&gt; console.log(&#39;Hello World!&#39;);</span><br><span class="line">Hello World!</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>ubuntu系统下nodejs的安装</title>
      <link href="front/node/nodejs-install/"/>
      <url>front/node/nodejs-install/</url>
      
        <content type="html"><![CDATA[<h2 id="nodejs安装"><a href="#nodejs安装" class="headerlink" title="nodejs安装"></a>nodejs安装</h2><p>推荐使用方法1进行安装</p><h3 id="方法1："><a href="#方法1：" class="headerlink" title="方法1："></a>方法1：</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl -sL https:&#x2F;&#x2F;deb.nodesource.com&#x2F;setup_8.x | sudo -E bash -</span><br><span class="line">sudo apt-get install -y nodejs</span><br></pre></td></tr></table></figure><h5 id="如果安装nodejs-9-x版本"><a href="#如果安装nodejs-9-x版本" class="headerlink" title="如果安装nodejs 9.x版本"></a>如果安装nodejs 9.x版本</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl -sL https:&#x2F;&#x2F;deb.nodesource.com&#x2F;setup_9.x | sudo -E bash -</span><br><span class="line">sudo apt-get install -y nodejs</span><br></pre></td></tr></table></figure><p>方法一使用了NodeSource提供的二进制包进行安装，NodeSource提供了常用的Linux系统（Ubuntu,CentOS,RedHat,Debian等）安装Node的二进制包，具体简介可以访问Linux通过二进制包安装nodejs</p><h3 id="方法2："><a href="#方法2：" class="headerlink" title="方法2："></a>方法2：</h3><p>在nodejs官方网站download页面中选择需要使用的版本,可以选择LTS或current,选择对应系统右键复制链接地址<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/node/node-install.png" alt="node官网">  </p><p>如果需要下载历史版本可以选择download页面底部PreviousReleases,也可以直接访问<a href="http://nodejs.org/dist/%E6%88%96https://nodejs.org/download/release/">http://nodejs.org/dist/或https://nodejs.org/download/release/</a>  </p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/node/node-install2.png" alt="historyversion"></p><p>当然你也可以使用<a href="https://www.taobao.com/">淘宝</a>npm镜像下载对应的<a href="https://npm.taobao.org/mirrors/node/">node版本</a>  </p><h5 id="下载nodejs压缩文件"><a href="#下载nodejs压缩文件" class="headerlink" title="下载nodejs压缩文件"></a>下载nodejs压缩文件</h5><p><code>wget https://nodejs.org/dist/v8.1.0/node-v8.1.0-linux-x64.tar.xz</code></p><h5 id="解压"><a href="#解压" class="headerlink" title="解压"></a>解压</h5><p><code>tar -xvf node-v8.1.0-linux-x64.tar.xz</code></p><h5 id="切换并查看当前node所在路径"><a href="#切换并查看当前node所在路径" class="headerlink" title="切换并查看当前node所在路径"></a>切换并查看当前node所在路径</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd node-v8.1.0-linux-x64&#x2F;bin</span><br><span class="line">pwd</span><br></pre></td></tr></table></figure><h5 id="查看node版本"><a href="#查看node版本" class="headerlink" title="查看node版本"></a>查看node版本</h5><p><code>./node -v</code></p><h5 id="将node和npm设置为全局"><a href="#将node和npm设置为全局" class="headerlink" title="将node和npm设置为全局"></a>将node和npm设置为全局</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo ln &#x2F;home&#x2F;ubuntu&#x2F;node-v8.1.0-linux-x64&#x2F;bin&#x2F;node &#x2F;usr&#x2F;local&#x2F;bin&#x2F;node</span><br><span class="line">sudo ln &#x2F;home&#x2F;ubuntu&#x2F;node-v8.1.0-linux-x64&#x2F;bin&#x2F;npm &#x2F;usr&#x2F;local&#x2F;bin&#x2F;npm</span><br><span class="line">pwd</span><br></pre></td></tr></table></figure><h3 id="方法3"><a href="#方法3" class="headerlink" title="方法3"></a>方法3</h3><p>也可以使用ubuntu自带apt-get安装,安装后使用node -v查看版本  </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install nodejs-legacy nodejs</span><br><span class="line">sudo apt-get install npm</span><br></pre></td></tr></table></figure><p>安装完成<br>推荐使用方法一，直接安装在系统环境/usr/bin目录下，之后使用npm -g安装其他插件也会安装到/usr/lib/node_modules’(需要使用sudo权限)‘。<br>如果使用方法二，将nodejs路径链接到/usr/local/bin目录下，则每次npm -g安装插件都会安装在nodejs原路径下的node_modules(比如/home/ubuntu/node-v8.1.0-linux-x64/lib/node_modules)，每次代码中引用插件也需要到此目录下去找</p><p>原文链接：<a href="https://blog.csdn.net/w20101310/article/details/73135388">https://blog.csdn.net/w20101310/article/details/73135388</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> ubuntu </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>npm常用命令</title>
      <link href="front/node/nodejs-npm-command/"/>
      <url>front/node/nodejs-npm-command/</url>
      
        <content type="html"><![CDATA[<h3 id="npm有啥用"><a href="#npm有啥用" class="headerlink" title="npm有啥用"></a>npm有啥用</h3><p>npm是一个node包管理和分发工具，已经成为了非官方的发布node模块（包）的标准。有了npm，可以很快的找到特定服务要使用的包，进行下载、安装以及管理已经安装的包。</p><h3 id="npm常用命令"><a href="#npm常用命令" class="headerlink" title="npm常用命令"></a>npm常用命令</h3><p>1、npm install moduleNames：安装Node模块<br>安装完毕后会产生一个node_modules目录，其目录下就是安装的各个node模块。</p><p>node的安装分为全局模式和本地模式。<br>一般情况下会以本地模式运行，包会被安装到和你的应用程序代码的本地node_modules目录下。<br>在全局模式下，Node包会被安装到Node的安装目录下的node_modules下。</p><p>全局安装命令为$npm install -g moduleName。<br>获知使用$npm set global=true来设定安装模式，$npm get global可以查看当前使用的安装模式。</p><p>示例：<br>npm install express<br>默认会安装express的最新版本，也可以通过在后面加版本号的方式安装指定版本，如npm install <a href="mailto:&#x65;&#120;&#112;&#x72;&#x65;&#x73;&#x73;&#64;&#x33;&#x2e;&#x30;&#x2e;&#54;">&#x65;&#120;&#112;&#x72;&#x65;&#x73;&#x73;&#64;&#x33;&#x2e;&#x30;&#x2e;&#54;</a></p><p>npm install <name> -g<br>将包安装到全局环境中</p><p>但是代码中，直接通过require()的方式是没有办法调用全局安装的包的。全局的安装是供命令行使用的，就好像全局安装了vmarket后，就可以在命令行中直接运行vm命令</p><p>npm install <name> –save<br>安装的同时，将信息写入package.json中项目路径中如果有package.json文件时，直接使用npm install方法就可以根据dependencies配置安装所有的依赖包，这样代码提交到github时，就不用提交node_modules这个文件夹了。</p><p>2、npm view moduleNames：查看node模块的package.json文件夹  </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">注意事项：如果想要查看package.json文件夹下某个标签的内容，可以使用$npm view moduleName labelName</span><br></pre></td></tr></table></figure><p>3、npm list：查看当前目录下已安装的node包  </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">注意事项：Node模块搜索是从代码执行的当前目录开始的，搜索结果取决于当前使用的目录中的node_modules下的内容。$ npm list parseable&#x3D;true可以目录的形式来展现当前安装的所有node包</span><br></pre></td></tr></table></figure><p>4、npm help：查看帮助命令</p><p>5、npm view moudleName dependencies：查看包的依赖关系</p><p>6、npm view moduleName repository.url：查看包的源文件地址</p><p>7、npm view moduleName engines：查看包所依赖的Node的版本</p><p>8、npm help folders：查看npm使用的所有文件夹</p><p>9、npm rebuild moduleName：用于更改包内容后进行重建</p><p>10、npm outdated：检查包是否已经过时，此命令会列出所有已经过时的包，可以及时进行包的更新</p><p>11、npm update moduleName：更新node模块</p><p>12、npm uninstall moudleName：卸载node模块</p><p>13、一个npm包是包含了package.json的文件夹，package.json描述了这个文件夹的结构。访问npm的json文件夹的方法如下：<br>$ npm help json<br>此命令会以默认的方式打开一个网页，如果更改了默认打开程序则可能不会以网页的形式打开。</p><p>14、发布一个npm包的时候，需要检验某个包名是否已存在<br>$ npm search packageName</p><p>15、npm init：会引导你创建一个package.json文件，包括名称、版本、作者这些信息等</p><p>16、npm root：查看当前包的安装路径<br>npm root -g：查看全局的包的安装路径</p><p>17、npm -v：查看npm安装的版本</p><p>除了本文介绍的部分外，NPM还提供了很多功能，package.json里也有很多其它有用的字段。</p><p>除了可以<a href="https://npmjs.org/doc/">查看官方文档</a> 外，这里再介绍一些NPM常用命令。</p>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>nodejs中的npm介绍</title>
      <link href="front/node/nodejs-npm/"/>
      <url>front/node/nodejs-npm/</url>
      
        <content type="html"><![CDATA[<p><a href="https://victorfengming.gitee.io/blog/nodejs-install/">nodejs安装</a>后，还需要安装npm，本文中小编会带大家安装它  </p><h3 id="NPM是什么？"><a href="#NPM是什么？" class="headerlink" title="NPM是什么？"></a>NPM是什么？</h3><p>NPM是随同NodeJS一起安装的包管理工具，能解决NodeJS代码部署上的很多问题，常见的使用场景有以下几种：</p><ul><li>允许用户从NPM服务器下载别人编写的第三方包到本地使用。</li><li>允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。</li><li>允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。 </li></ul><p>由于新版的nodejs已经集成了npm，所以之前npm也一并安装好了。同样可以通过输入<br>“npm -v”<br>来测试是否成功安装。命令如下，出现版本提示表示安装成功:  </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ npm -v</span><br><span class="line">2.3.0 </span><br></pre></td></tr></table></figure><p>如果你安装的是旧版本的 npm，可以很容易得通过 npm 命令来升级，命令如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ sudo npm install npm -g</span><br><span class="line">&#x2F;usr&#x2F;local&#x2F;bin&#x2F;npm -&gt; &#x2F;usr&#x2F;local&#x2F;lib&#x2F;node_modules&#x2F;npm&#x2F;bin&#x2F;npm-cli.js</span><br><span class="line">npm@2.14.2 &#x2F;usr&#x2F;local&#x2F;lib&#x2F;node_modules&#x2F;npm</span><br></pre></td></tr></table></figure><p>如果是 Window 系统使用以下命令即可：<br><code>npm install npm -g</code>  </p><h3 id="全局安装与本地安装"><a href="#全局安装与本地安装" class="headerlink" title="全局安装与本地安装"></a>全局安装与本地安装</h3><p>npm 的包安装分为本地安装（local）、全局安装（global）两种，从敲的命令行来看，差别只是有没有-g而已，比如</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install express          # 本地安装</span><br><span class="line">npm install express -g   # 全局安装</span><br></pre></td></tr></table></figure><p>如果出现以下错误：<br><code>npm err! Error: connect ECONNREFUSED 127.0.0.1:8087 </code><br>解决办法为：<br><code>$ npm config set proxy null</code>  </p><h4 id="本地安装"><a href="#本地安装" class="headerlink" title="本地安装"></a>本地安装</h4><ol><li>将安装包放在 ./node_modules 下（运行 npm 命令时所在的目录），如果没有 node_modules 目录，会在当前执行 npm 命令的目录下生成 node_modules 目录。</li><li>可以通过 require() 来引入本地安装的包。</li></ol><h4 id="全局安装"><a href="#全局安装" class="headerlink" title="全局安装"></a>全局安装</h4><ol><li>将安装包放在 /usr/local 下或者你 node 的安装目录。</li><li>可以直接在命令行里使用。</li></ol><p>如果你希望具备两者功能，则需要在两个地方安装它或使用 npm link。</p><h3 id="NPM-应用"><a href="#NPM-应用" class="headerlink" title="NPM 应用"></a>NPM 应用</h3><p>NPM建立了一个NodeJS生态圈，NodeJS开发者和用户可以在里边互通有无。以下介绍NPM应用的三种场景：</p><h4 id="下载第三方包"><a href="#下载第三方包" class="headerlink" title="下载第三方包"></a>下载第三方包</h4><p>我们可以使用以下命令来下载第三方包。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ npm install argv</span><br><span class="line">...</span><br><span class="line">argv@0.0.2 node_modules\argv</span><br></pre></td></tr></table></figure><p>下载好之后，argv包就放在了工程目录下的node_modules目录中，因此在代码中只需要通过require(‘argv’)的方式就好，无需指定第三方包路径。</p><p>以上命令默认下载最新版第三方包，如果想要下载指定版本的话，可以在包名后边加上@<version>，例如通过以下命令可下载0.0.1版的argv。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ npm install argv@0.0.1</span><br><span class="line">...</span><br><span class="line">argv@0.0.1 node_modules\argv</span><br></pre></td></tr></table></figure><p>NPM对package.json的字段做了扩展，允许在其中申明第三方包依赖。因此，上边例子中的package.json可以改写如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    &quot;name&quot;: &quot;node-echo&quot;,</span><br><span class="line">    &quot;main&quot;: &quot;.&#x2F;lib&#x2F;echo.js&quot;,</span><br><span class="line">    &quot;dependencies&quot;: &#123;</span><br><span class="line">        &quot;argv&quot;: &quot;0.0.2&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;    </span><br></pre></td></tr></table></figure><p>这样处理后，在工程目录下就可以使用npm install命令批量安装第三方包了。</p><p>更重要的是，当以后node-echo也上传到了NPM服务器，别人下载这个包时，NPM会根据包中申明的第三方包依赖自动下载进一步依赖的第三方包。</p><p>例如，使用npm install node-echo命令时，NPM会自动创建以下目录结构。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">- project&#x2F;</span><br><span class="line">    - node_modules&#x2F;</span><br><span class="line">        - node-echo&#x2F;</span><br><span class="line">            - node_modules&#x2F;</span><br><span class="line">                + argv&#x2F;</span><br><span class="line">            ...</span><br><span class="line">    ...</span><br><span class="line"></span><br><span class="line">&#96;&#96;&#96;    </span><br><span class="line">如此一来，用户只需关心自己直接使用的第三方包，不需要自己去解决所有包的依赖关系。</span><br><span class="line"></span><br><span class="line">##### 安装命令行程序</span><br><span class="line">从NPM服务上下载安装一个命令行程序的方法与第三方包类似。</span><br><span class="line"></span><br><span class="line">例如上例中的node-echo提供了命令行使用方式，只要node-echo自己配置好了相关的package.json字段，对于用户而言，只需要使用以下命令安装程序。</span><br><span class="line"></span><br><span class="line">&#96;$ npm install node-echo -g&#96;</span><br><span class="line">参数中的-g表示全局安装，因此node-echo会默认安装到以下位置，并且NPM会自动创建好Linux系统下需要的软链文件或Windows系统下需要的.cmd文件。</span><br></pre></td></tr></table></figure><ul><li><p>/usr/local/               # Linux系统下</p><ul><li>lib/node_modules/<ul><li>node-echo/<br>…</li></ul></li><li>bin/<br>  node-echo<br>  …<br>…</li></ul></li><li><p>%APPDATA%\npm\            # Windows系统下</p><ul><li>node_modules\<ul><li>node-echo<br>…<br>node-echo.cmd<br>…<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">##### 发布代码</span><br><span class="line">第一次使用NPM发布代码前需要注册一个账号。终端下运行npm adduser，之后按照提示做即可。</span><br><span class="line"></span><br><span class="line">账号注册完成后，接着我们需要编辑package.json文件，加入NPM必需的字段。接着上边node-echo的例子，package.json里必要的字段如下。</span><br></pre></td></tr></table></figure>{<br>“name”: “node-echo”,           # 包名，在NPM服务器上须要保持唯一<br>“version”: “1.0.0”,            # 当前版本号<br>“dependencies”: {              # 第三方包依赖，需要指定包名和版本号<br>“argv”: “0.0.2”<br>},<br>“main”: “./lib/echo.js”,       # 入口模块位置<br>“bin” : {<br>“node-echo”: “./bin/node-echo”      # 命令行程序名和主模块位置<br>}<br>}<br>```<br>之后，我们就可以在package.json所在目录下运行npm publish发布代码了。</li></ul></li></ul></li></ul><h3 id="版本号"><a href="#版本号" class="headerlink" title="版本号"></a>版本号</h3><p>使用NPM下载和发布代码时都会接触到版本号。NPM使用语义版本号来管理代码，这里简单介绍一下。</p><p>语义版本号分为X.Y.Z三位，分别代表主版本号、次版本号和补丁版本号。当代码变更时，版本号按以下原则更新。</p><p>如果只是修复bug，需要更新Z位。<br>如果是新增了功能，但是向下兼容，需要更新Y位。<br>如果有大变动，向下不兼容，需要更新X位。<br>版本号有了这个保证后，在申明第三方包依赖时，除了可依赖于一个固定版本号外，还可依赖于某个范围的版本号。例如”argv”: “0.0.x”表示依赖于0.0.x系列的最新版argv。</p><p>NPM支持的所有版本号范围指定方式可以查看<a href="https://npmjs.org/doc/files/package.json.html#dependencies">官方文档</a> 。</p>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Node.js REPL(交互式解释器)</title>
      <link href="front/node/nodejs-repl/"/>
      <url>front/node/nodejs-repl/</url>
      
        <content type="html"><![CDATA[<h3 id="Node-js-REPL-交互式解释器"><a href="#Node-js-REPL-交互式解释器" class="headerlink" title="Node.js REPL(交互式解释器)"></a>Node.js REPL(交互式解释器)</h3><p>Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境，类似 Window 系统的终端或 Unix/Linux shell，我们可以在终端中输入命令，并接收系统的响应。</p><p>REPL 的交互式的编程环境可以实时的验证你所编写的代码，非常适合于验证 Node.js 和 JavaScript 的相关 API。</p><p>Node 自带了交互式解释器，可以执行以下任务：</p><ul><li><p>读取 - 读取用户输入，解析输入了Javascript 数据结构并存储在内存中。</p></li><li><p>执行 - 执行输入的数据结构</p></li><li><p>打印 - 输出结果</p></li><li><p>循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。</p></li></ul><p>Node 的交互式解释器可以很好的调试 Javascript 代码。</p><p>开始学习 REPL</p><p>我们可以输入以下命令来启动 Node 的终端：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ node</span><br><span class="line">&gt; </span><br></pre></td></tr></table></figure><p>这时我们就可以在 &gt; 后输入简单的表达式，并按下回车键来计算结果。</p><h3 id="简单的表达式运算"><a href="#简单的表达式运算" class="headerlink" title="简单的表达式运算"></a>简单的表达式运算</h3><p>接下来让我们在 Node.js REPL 的命令行窗口中执行简单的数学运算：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">$ node</span><br><span class="line">&gt; <span class="number">1</span> +<span class="number">4</span></span><br><span class="line"><span class="number">5</span></span><br><span class="line">&gt; <span class="number">5</span> / <span class="number">2</span></span><br><span class="line"><span class="number">2.5</span></span><br><span class="line">&gt; <span class="number">3</span> * <span class="number">6</span></span><br><span class="line"><span class="number">18</span></span><br><span class="line">&gt; <span class="number">4</span> - <span class="number">1</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line">&gt; <span class="number">1</span> + ( <span class="number">2</span> * <span class="number">3</span> ) - <span class="number">4</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line">&gt;</span><br></pre></td></tr></table></figure><h3 id="使用变量"><a href="#使用变量" class="headerlink" title="使用变量"></a>使用变量</h3><p>你可以将数据存储在变量中，并在你需要的使用它。</p><p>变量声明需要使用 var 关键字，如果没有使用 var 关键字变量会直接打印出来。</p><p>使用 var 关键字的变量可以使用 console.log() 来输出变量。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">$ node</span><br><span class="line">&gt; x = <span class="number">10</span></span><br><span class="line"><span class="number">10</span></span><br><span class="line">&gt; <span class="keyword">var</span> y = <span class="number">10</span></span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line">&gt; x + y</span><br><span class="line"><span class="number">20</span></span><br><span class="line">&gt; <span class="built_in">console</span>.log(<span class="string">&quot;Hello World&quot;</span>)</span><br><span class="line">Hello World</span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line">&gt; <span class="built_in">console</span>.log(<span class="string">&quot;www.w3cschool.cn&quot;</span>)</span><br><span class="line">www.w3cschool.cn</span><br><span class="line"><span class="literal">undefined</span></span><br></pre></td></tr></table></figure><h3 id="多行表达式"><a href="#多行表达式" class="headerlink" title="多行表达式"></a>多行表达式</h3><p>Node REPL 支持输入多行表达式，这就有点类似 JavaScript。接下来让我们来执行一个 do-while 循环：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">$ node</span><br><span class="line">&gt; <span class="keyword">var</span> x = <span class="number">0</span></span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line">&gt; <span class="keyword">do</span> &#123;</span><br><span class="line">... x++;</span><br><span class="line">... <span class="built_in">console</span>.log(<span class="string">&quot;x: &quot;</span> + x);</span><br><span class="line">... &#125; <span class="keyword">while</span> ( x &lt; <span class="number">5</span> );</span><br><span class="line">x: <span class="number">1</span></span><br><span class="line">x: <span class="number">2</span></span><br><span class="line">x: <span class="number">3</span></span><br><span class="line">x: <span class="number">4</span></span><br><span class="line">x: <span class="number">5</span></span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line">&gt;</span><br></pre></td></tr></table></figure><p>… 三个点的符号是系统自动生成的，你回车换行后即可。Node 会自动检测是否为连续的表达式。</p><p>下划线(<em>)变量<br>你可以使用下划线(</em>)获取表达式的运算结果：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">$ node</span><br><span class="line">&gt; <span class="keyword">var</span> x = <span class="number">10</span></span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line">&gt; <span class="keyword">var</span> y = <span class="number">20</span></span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line">&gt; x + y</span><br><span class="line"><span class="number">30</span></span><br><span class="line">&gt; <span class="keyword">var</span> sum = _</span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line">&gt; <span class="built_in">console</span>.log(sum)</span><br><span class="line"><span class="number">30</span></span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line">&gt;</span><br></pre></td></tr></table></figure><h3 id="REPL-命令"><a href="#REPL-命令" class="headerlink" title="REPL 命令"></a>REPL 命令</h3><ul><li><p>ctrl + c - 退出当前终端。</p></li><li><p>ctrl + c 按下两次 - 退出 Node REPL。</p></li><li><p>ctrl + d - 退出 Node REPL.</p></li><li><p>向上/向下 键 - 查看输入的历史命令</p></li><li><p>tab 键 - 列出当前命令</p></li><li><p>.help - 列出使用命令</p></li><li><p>.break - 退出多行表达式</p></li><li><p>.clear - 退出多行表达式</p></li><li><p>.save filename - 保存当前的 Node REPL 会话到指定文件</p></li><li><p>.load filename - 载入当前 Node REPL 会话的文件内容。</p></li></ul><h3 id="停止-REPL"><a href="#停止-REPL" class="headerlink" title="停止 REPL"></a>停止 REPL</h3><p>前面我们已经提到按下两次 ctrl + c 建就能退出 REPL:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ node</span><br><span class="line">&gt;</span><br><span class="line">(^C again to quit)</span><br><span class="line">&gt;</span><br></pre></td></tr></table></figure><h3 id="推荐阅读"><a href="#推荐阅读" class="headerlink" title="推荐阅读"></a>推荐阅读</h3><p><a href="https://www.w3cschool.cn/javascript_guide/javascript_guide-9hey2691.html">JavaScript中的console对象</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> node </tag>
            
            <tag> background </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Linux常用命令</title>
      <link href="linux/linux-frequent-command/"/>
      <url>linux/linux-frequent-command/</url>
      
        <content type="html"><![CDATA[<h1 id="Linux常用命令简洁版"><a href="#Linux常用命令简洁版" class="headerlink" title="Linux常用命令简洁版"></a>Linux常用命令简洁版</h1><h3 id="1-Linux管理文件和目录的命令"><a href="#1-Linux管理文件和目录的命令" class="headerlink" title="1. Linux管理文件和目录的命令"></a>1. Linux管理文件和目录的命令</h3><p>pwd     显示当前目录<br>ls      查看目录下的内容<br>cd      改变目录<br>cat     显示文件的内容<br>gerp    在文件中查找某字符<br>cp      复制文件<br>touch   创建文件<br>mv      移动文件<br>rm      删除文件<br>rmdir   删除目录  </p><h3 id="2-有关磁盘空间的命令"><a href="#2-有关磁盘空间的命令" class="headerlink" title="2.有关磁盘空间的命令"></a>2.有关磁盘空间的命令</h3><p>mount   挂载文件系统<br>umount  卸载已挂载上的文件系统<br>df      检查各个磁盘分区和已经挂在上来的文件系统的磁盘空间<br>fsck    主要是检查和修复Linux文件系统  </p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>linux学习笔记</title>
      <link href="linux/ydma.cn-linux/"/>
      <url>linux/ydma.cn-linux/</url>
      
        <content type="html"><![CDATA[<h3 id="搭建网站的过程"><a href="#搭建网站的过程" class="headerlink" title="搭建网站的过程"></a>搭建网站的过程</h3><p>产品设计    -&gt; 产品经理<br>    选准公司的技术方向<br>    针对目标用户群<br>    考虑用户的需求和使用习惯<br>    真正的关乎与公司的生死存亡的人是产品设计和你的市场<br>    产品设计和编程人员一直有问题</p><p>网页布局，字体调整，图片设计<br>网站程序的编写<br>把网站发布到服务器的web服务中<br>把服务器链接到网络中    </p><p>计算机行业分类<br>    产品经理<br>    设计类方向（UI UE）<br>    开发方向（HTML，PHP，Java，C）<br>    网络方向（思科，华为，华三）<br>    运维方向（Linux，云计算） </p><p>网络工程方向：<br>    CCNA<br>    CCNP<br>    CCIE</p><p>IT<br>    编程<br>    运维<br>    网络</p><p>运维方向优点<br>    行业需求量逐年增加<br>    行业薪资逐渐高于行业平均薪资<br>    技术淘汰速度非常慢 Linux<br>    从业压力较小，是所有技术类行业中最小的</p><p>软件更新阶段是很快的<br>比如说<br>嵌入式开发：智能化（拥有CPU，拥有可以升级和配置操作系统）<br>    开发操作系统，和软件</p><p>Android出现：Google<br>Linux运维技术更新速度很慢，不像Java，<br>比如你是学习java的，你要不一直在学习新的技术，你就会被行业所淘汰<br>但是像这种Linux运维技术七更新的周期是很短的<br>相对来说要稳定的多<br>只要服务器不出问题，你就没事情可以干</p><p>操作系统介绍<br>Windows<br>linux<br>unix</p><p>我们以后主要要学的就是Linux<br>我们是已就业为主，不是像大学的这种应试教育<br>Windows的优点<br>    简单那<br>    易用<br>    软件支持度高<br>    界面漂亮</p><p>我们维护的不是简单漂亮的，而是性能高的  </p><p>Linux优点<br>    开源<br>    免费<br>    稳定 windows稳定性要下降20%（Linux中的软件安装完大小基本上不会改变）<br>    安全</p><h3 id="课程体系介绍"><a href="#课程体系介绍" class="headerlink" title="课程体系介绍"></a>课程体系介绍</h3><h3 id="集群是什么？"><a href="#集群是什么？" class="headerlink" title="集群是什么？"></a>集群是什么？</h3><p>集群是一组相互独立的，通过告诉网络互联的计算机，它们构成了一个组，病以单一系统的模式加以管理。一个客户与集群相互作用时，集群像是一个独立的服务器。集群配置是用于提高可用性和缩放性</p><h3 id="普通服务器"><a href="#普通服务器" class="headerlink" title="普通服务器"></a>普通服务器</h3><p>1-1.5万 1U机架式服务器</p><p>端游（lol，魔兽世界） 页游（斗地主，偷菜）</p><p>其实是端游更省服务器，端游都是装在本机上的<br>而页游所有是资源都是在服务区上的</p><p>集群的分类<br>    科学计算型集群<br>    负载均衡性集群<br>    高可用性集群</p><p>ls<br>ls -a 查看隐藏文件<br>隐藏文件的意义：<br>    在Linux和Windows中很方便的查看隐藏文件<br>    隐藏文件是告诉用户你轻易的不要动它</p><pre><code>在Linux中，以点开头的就是隐藏文件</code></pre><p>ls -l 查看文件详细信息<br>    所有者 所属组 其他人</p><p>linux文件基本属性</p><h3 id="Linux中第一个字符代表这个文件是目录，文件或链接等等"><a href="#Linux中第一个字符代表这个文件是目录，文件或链接等等" class="headerlink" title="Linux中第一个字符代表这个文件是目录，文件或链接等等"></a>Linux中第一个字符代表这个文件是目录，文件或链接等等</h3><ul><li>当为[d]则是目录</li><li>当为[-]则是文件</li><li>若是[l]则表示链接文档（link file）；</li><li>若是[b]则为装置文件里面的可供存储的接口设备（可随机存取装置）；</li><li>若是[c]则表示为装置文件里面的穿行端口设备，例如键盘，鼠标（一次性读取装置）。</li></ul><h3 id="rwx参数"><a href="#rwx参数" class="headerlink" title="rwx参数"></a>rwx参数</h3><p>r - 读权限<br>w - 写权限<br>x - 执行权限</p><h3 id="更改文件的属性"><a href="#更改文件的属性" class="headerlink" title="更改文件的属性"></a>更改文件的属性</h3><h3 id="linux-文件与目录管理"><a href="#linux-文件与目录管理" class="headerlink" title="linux 文件与目录管理"></a>linux 文件与目录管理</h3><p>我们知道Linux目录结构为数状结构，最顶级的目录为根目录/<br>其他目录通过挂在可以将它们添加到数中，通过解除挂载可以移除它们</p><h3 id="绝对路径"><a href="#绝对路径" class="headerlink" title="绝对路径"></a>绝对路径</h3><p>路径的写法，由根目录/写起，比如“/usr/share/doc</p><h3 id="相对路径"><a href="#相对路径" class="headerlink" title="相对路径"></a>相对路径</h3><p>路径的写法，不是由/写起的，比如 有/usr/share/doc要到/share/man 底下时，可以写成：cd ../man 这就是相对路径的写法啦！</p><h3 id="处理目录常用命令"><a href="#处理目录常用命令" class="headerlink" title="处理目录常用命令"></a>处理目录常用命令</h3><p>ls：列出目录<br>cd：切换目录<br>pwd：显示当前目录<br>mkdir：创建一个新的目录<br>rmdir：删除一个空的目录<br>cp：复制文件或者目录<br>rm：移除文件或者目录<br>mv：移动文件与目录，文件重命名</p><p>可以使用man[命令]来查看各个命令的使用文档，如：man cp</p><h3 id="ls（列出目录）"><a href="#ls（列出目录）" class="headerlink" title="ls（列出目录）"></a>ls（列出目录）</h3><p>在Linux系统当中，ls命令可能是最经常被使用的<br>语法<br>[root@www ~]# ls [-aAdfFhilnrRSt] 目录名称<br>[root@www ~]# ls [–color={never,auto,always}] 目录名称<br>[root@www ~]# ls [–full-time] 目录名称</p><p>参数与选项：<br>-a ： 全部的文件，连同隐藏档（开头为.的文件）一起列出来（常用）<br>-d ：仅列出目录本身，而不是列出目录内的文件数据（常用）<br>-l ：长数据串列出，包含文件的属性与权限等等数据；（常用）<br>将家目录下的所有文件列出来（含属性与隐藏档）<br>[root@www ~]# ls -al ～</p><h3 id="cd（切换目录）"><a href="#cd（切换目录）" class="headerlink" title="cd（切换目录）"></a>cd（切换目录）</h3><p>cd 是 change directory的缩写，这是用来变换工作目录的命令<br>语法：<br>cd [相对路径或绝对路径]</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">#使用 mkdir 命令创建w3cschool.cn目录</span><br><span class="line">[root@www ~]# mkdir w3cschool.cn</span><br><span class="line"></span><br><span class="line">#使用绝对路径切换到w3cschool.cn目录</span><br><span class="line">[root@www ~]# cd &#x2F;root&#x2F;w3cschool.cn&#x2F;</span><br><span class="line"></span><br><span class="line">#使用相对路径切换到w3cschool.cn目录</span><br><span class="line">[root@www ~]# cd .&#x2F;w3cschool.cn&#x2F;</span><br><span class="line"></span><br><span class="line"># 表示回到自己的家目录，亦即是 &#x2F;root 这个目录</span><br><span class="line">[root@www w3cschool.cn]# cd ~</span><br><span class="line"></span><br><span class="line"># 表示去到目前的上一级目录，亦即是 &#x2F;root 的上一级目录的意思；</span><br><span class="line">[root@www ~]# cd ..</span><br></pre></td></tr></table></figure><h3 id="pwd（显示目前所在的目录）"><a href="#pwd（显示目前所在的目录）" class="headerlink" title="pwd（显示目前所在的目录）"></a>pwd（显示目前所在的目录）</h3><p>pwd 是 print working directory的缩写，也就是显示目前所在目录的命令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">[root@www ~]# pwd [-P]</span><br><span class="line">选项与参数：</span><br><span class="line">-P  ：显示出确实的路径，而非使用连结 (link) 路径。</span><br><span class="line"></span><br><span class="line">范例：单纯显示出目前的工作目录：</span><br><span class="line">[root@www ~]# pwd</span><br><span class="line">&#x2F;root   &lt;&#x3D;&#x3D; 显示出目录啦～  </span><br><span class="line"></span><br><span class="line">范例：显示出实际的工作目录，而非连结档本身的目录名而已 </span><br><span class="line">[root@www ~]# cd &#x2F;var&#x2F;mail   &lt;&#x3D;&#x3D;注意，&#x2F;var&#x2F;mail是一个连结档 </span><br><span class="line">[root@www mail]# pwd </span><br><span class="line">&#x2F;var&#x2F;mail         &lt;&#x3D;&#x3D;列出目前的工作目录 </span><br><span class="line">[root@www mail]# pwd -P </span><br><span class="line">&#x2F;var&#x2F;spool&#x2F;mail   &lt;&#x3D;&#x3D;怎么回事？有没有加 -P 差很多～ </span><br><span class="line">[root@www mail]# ls -ld &#x2F;var&#x2F;mail </span><br><span class="line">lrwxrwxrwx 1 root root 10 Sep  4 17:54 &#x2F;var&#x2F;mail -&gt; spool&#x2F;mail</span><br><span class="line"># 看到这里应该知道为啥了吧？因为 &#x2F;var&#x2F;mail 是连结档，连结到 &#x2F;var&#x2F;spool&#x2F;mail </span><br><span class="line"># 所以，加上 pwd -P 的选项后，会不以连结档的数据显示，而是显示正确的完整路径啊！</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="mkdir-创建新目录"><a href="#mkdir-创建新目录" class="headerlink" title="mkdir (创建新目录)"></a>mkdir (创建新目录)</h3><p>如果想要创建新的目录的话，那么就使用mkdir（make directory）吧<br>语法：<br>mkdir [-mp] 目录名称<br>选项与参数<br>-m ：配置文件的权限！直接配置，不需要看默认权限（umask）的脸色～<br>-p ：帮助你直接将所需要的目录（包含上一级目录）递归创建起来</p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> basis </tag>
            
            <tag> server </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>vim编辑器不能使用backspace问题解决方案</title>
      <link href="linux/vim-backspace/"/>
      <url>linux/vim-backspace/</url>
      
        <content type="html"><![CDATA[<h3 id="在-ubuntu-的命令行中使用-vi-命令编辑文件，遇到方向键与退格键无法正常使用时可通过如下方式解决-："><a href="#在-ubuntu-的命令行中使用-vi-命令编辑文件，遇到方向键与退格键无法正常使用时可通过如下方式解决-：" class="headerlink" title="在 ubuntu 的命令行中使用 vi 命令编辑文件，遇到方向键与退格键无法正常使用时可通过如下方式解决 ："></a>在 ubuntu 的命令行中使用 vi 命令编辑文件，遇到方向键与退格键无法正常使用时可通过如下方式解决 ：</h3><h3 id="第一步"><a href="#第一步" class="headerlink" title="第一步"></a>第一步</h3><p>1、打开 /etc/vim/vimrc.tiny 文件，</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /etc/vim  </span><br><span class="line">sudo gedit vimrc.tiny  </span><br></pre></td></tr></table></figure><h3 id="第二步"><a href="#第二步" class="headerlink" title="第二步"></a>第二步</h3><p>在编辑器中<br>将“compatible”改成“nocompatible”非兼容模式<br>这样就可以解决方向键变 ABCD 的问题了。</p><h3 id="第三步"><a href="#第三步" class="headerlink" title="第三步"></a>第三步</h3><p>添加 set backspace=2 语句，这样 Backspace 退格键恢复正常使用。<br>完美解决  </p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Linux </tag>
            
            <tag> ubuntu </tag>
            
            <tag> vim </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>vim中批量添加注释</title>
      <link href="linux/vim-g/"/>
      <url>linux/vim-g/</url>
      
        <content type="html"><![CDATA[<h3 id="方法一-：块选择模式"><a href="#方法一-：块选择模式" class="headerlink" title="方法一 ：块选择模式"></a>方法一 ：块选择模式</h3><h5 id="批量注释："><a href="#批量注释：" class="headerlink" title="批量注释："></a>批量注释：</h5><p>Ctrl + v 进入块选择模式，然后移动光标选中你要注释的行，再按大写的 I 进入行首插入模式输入注释符号如 // 或 #，输入完毕之后，按两下 ESC，Vim 会自动将你选中的所有行首都加上注释，保存退出完成注释。</p><h5 id="取消注释："><a href="#取消注释：" class="headerlink" title="取消注释："></a>取消注释：</h5><p>Ctrl + v 进入块选择模式，选中你要删除的行首的注释符号，注意 // 要选中两个，选好之后按 d 即可删除注释，ESC 保存退出。</p><h3 id="方法二-替换命令"><a href="#方法二-替换命令" class="headerlink" title="方法二: 替换命令"></a>方法二: 替换命令</h3><h5 id="批量注释。"><a href="#批量注释。" class="headerlink" title="批量注释。"></a>批量注释。</h5><p>使用下面命令在指定的行首添加注释。</p><p>使用名命令格式： :起始行号,结束行号s/^/注释符/g（注意冒号）。</p><h5 id="取消注释：-1"><a href="#取消注释：-1" class="headerlink" title="取消注释："></a>取消注释：</h5><p>使用名命令格式： :起始行号,结束行号s/^注释符//g（注意冒号）。</p><h3 id="例子："><a href="#例子：" class="headerlink" title="例子："></a>例子：</h3><p>1、在 10 - 20 行添加 // 注释<br><code>:10,20s#^#//#g</code><br>2、在 10 - 20 行删除 // 注释<br><code>:10,20s#^//##g</code><br>3、在 10 - 20 行添加 # 注释<br><code>:10,20s/^/#/g</code><br>4、在 10 - 20 行删除 # 注释<br><code>:10,20s/#//g</code></p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> basis </tag>
            
            <tag> vim </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>前端相关知识索引</title>
      <link href="front/html-css-js/"/>
      <url>front/html-css-js/</url>
      
        <content type="html"><![CDATA[<h3 id="HTML相关"><a href="#HTML相关" class="headerlink" title="HTML相关"></a>HTML相关</h3><ul><li><a href="https://blog.csdn.net/qq_40223983/article/details/96093661">HTML概述和基本结构</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96093970">HTML中Head头</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96094078">HTML标题</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96094383">HTML段落,换行,字符实体</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96094450">HTML块,含样式的标签</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96094542">HTML中的图片</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96094772">HTML中的链接</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96098113">HTML中的列表</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96099336">HTML中的表格</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96099526">HTML中的表单</a></li></ul><h3 id="CSS相关"><a href="#CSS相关" class="headerlink" title="CSS相关"></a>CSS相关</h3><ul><li><a href="https://blog.csdn.net/qq_40223983/article/details/96144156">Css基本语法及页面引用</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96144387">Css中的选择器</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96144619">Css颜色和文本字体</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96265073">CSS边框,背景,边距,溢出</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96265543">CSS中的盒子</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96266133">CSS中的块元素,内联元素,内联块元素</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96266892">CSS中的定位</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96266677">CSS之浮动</a></li></ul><h3 id="JS相关"><a href="#JS相关" class="headerlink" title="JS相关"></a>JS相关</h3><ul><li><a href="https://blog.csdn.net/qq_40223983/article/details/96565365">JavaScript的使用场景</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96565972">JavaScript中的变量</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96566519">JavaScript中的数据类型转换</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96566704">JavaScript中的运算符</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96567013">JavaScript中的流程控制</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96567141">JavaScript中的循环</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96567334">JavaScript中的元素获取与操作</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96568231">JavaScript中的定时器</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96568915">JavaScript中的函数</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96572724">JavaScript中的对象</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96572942">JavaScript中的数组</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96573223">JavaScript中的数学对象Math</a></li><li><a href="https://blog.csdn.net/qq_40223983/article/details/96573403">JavaScript中的正则</a></li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> web </tag>
            
            <tag> index </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>git个人整理总结</title>
      <link href="git/progit-min/"/>
      <url>git/progit-min/</url>
      
        <content type="html"><![CDATA[<html lang="zh-CN"><head>    <meta charset="utf-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">    <title>git 简明指南</title>    <link href='http://fonts.useso.com/css?family=Chelsea+Market' rel='stylesheet' type='text/css'>    <link rel="stylesheet" href="css/normalize.min.css" type="text/css">    <link rel="stylesheet" href="css/style.css" type="text/css"></head><body>    <div class="scrollblock block-title">               <img src= "/img/loading.gif" data-lazy-src="img/arrow.png" alt="" />    </div>    <!-- setup -->    <a name="setup"></a>    <div class="scrollblock block-setup">        <h3>想要使用git，要先进行git的安装，这里有三种版本供大家选择</h3>        <p>            <a href="http://git-scm.com/download/mac">下载 git OSX 版</a>        </p>        <p>            <a href="http://msysgit.github.io">下载 git Windows 版</a>        </p>        <p>            <a href="http://git-scm.com/download/linux">下载 git Linux 版</a>        </p>    </div>    <a name="create"></a>    <div class="scrollblock block-create">        <h3>创建一个新仓库，开始你的git之旅吧</h3>        <p>            创建新文件夹，打开，然后执行 <br />            <code>git init</code><br />            以创建新的 git 仓库。        </p>    </div>    <a name="checkout"></a>    <div class="scrollblock block-checkout">        <h3>检出仓库，相当于克隆到本地</h3>        <p>            执行如下命令以创建一个本地仓库的克隆版本：<br />            <code>git clone /path/to/repository</code> <br />            如果是远端服务器上的仓库，你的命令会是这个样子：<br />            <code>git clone username@host:/path/to/repository</code>        </p>    </div>    <a name="trees"></a>    <div class="scrollblock block-trees">        <h3>关于工作流的相关说明</h3>        <p>            你的本地仓库由 git 维护的三棵“树”组成。第一个是你的 <code>工作目录</code>，它持有实际文件；第二个是 <code>暂存区（Index）</code>，它像个缓存区域，临时保存你的改动；最后是 <code>HEAD</code>，它指向你最后一次提交的结果。        </p>        <img src= "/img/loading.gif" data-lazy-src="img/trees.png" alt="" />    </div>    <a name="add"></a>    <div class="scrollblock block-add">        <h3>添加和提交你的更改，让你的贡献生效</h3>        <p>            你可以提出更改（把它们添加到暂存区），使用如下命令：<br />            <code>git add &lt;filename&gt;</code><br />            <code>git add *</code><br />            这是 git 基本工作流程的第一步；使用如下命令以实际提交改动：<br />            <code>git commit -m "代码提交信息"</code><br />            现在，你的改动已经提交到了 <b>HEAD</b>，但是还没到你的远端仓库。        </p>    </div>    <a name="push"></a>    <div class="scrollblock block-remote">        <h3>推送改动-将本地的数据push到远程端</h3>        <p>            你的改动现在已经在本地仓库的 <b>HEAD</b> 中了。执行如下命令以将这些改动提交到远端仓库：<br />            <code>git push origin master</code><br />            可以把 <i>master</i> 换成你想要推送的任何分支。            <br /><br />            如果你还没有克隆现有仓库，并欲将你的仓库连接到某个远程服务器，你可以使用如下命令添加：<br />            <code>git remote add origin &lt;server&gt;</code><br />            如此你就能够将你的改动推送到所添加的服务器上去了。<br />        </p>    </div>    <a name="branching"></a>    <div class="scrollblock block-branching">        <h3>分支-最重要的概念</h3>        <p>            分支是用来将特性开发绝缘开来的。在你创建仓库的时候，<i>master</i> 是“默认的”分支。在其他分支上进行开发，完成后再将它们合并到主分支上。        </p>        <img src= "/img/loading.gif" data-lazy-src="img/branches.png" alt="" />        <p>            创建一个叫做“feature_x”的分支，并切换过去：<br />            <code>git checkout -b feature_x</code><br />            切换回主分支：<br />            <code>git checkout master</code><br />            再把新建的分支删掉：<br />            <code>git branch -d feature_x</code><br />            除非你将分支推送到远端仓库，不然该分支就是 <i>不为他人所见的</i>：<br />            <code>git push origin &lt;branch&gt;</code>        </p>    </div>    <a name="update"></a>    <div class="scrollblock block-merging">        <h3>更新与合并</h3>        <p>            要更新你的本地仓库至最新改动，执行：<br />            <code>git pull</code><br />            以在你的工作目录中 <i>获取（fetch）</i> 并 <i>合并（merge）</i> 远端的改动。<br />            要合并其他分支到你的当前分支（例如 master），执行：<br />            <code>git merge &lt;branch&gt;</code><br />            在这两种情况下，git 都会尝试去自动合并改动。遗憾的是，这可能并非每次都成功，并可能出现<i>冲突（conflicts）</i>。            这时候就需要你修改这些文件来手动合并这些<i>冲突（conflicts）</i>。改完之后，你需要执行如下命令以将它们标记为合并成功：<br />            <code>git add &lt;filename&gt;</code><br />            在合并改动之前，你可以使用如下命令预览差异：<br />            <code>git diff &lt;source_branch&gt; &lt;target_branch&gt;</code>        </p>    </div>    <a name="tagging"></a>    <div class="scrollblock block-tagging">        <h3>关于标签</h3>        <p>            为软件发布创建标签是推荐的。这个概念早已存在，在 SVN 中也有。你可以执行如下命令创建一个叫做 <i>1.0.0</i> 的标签：<br />            <code>git tag 1.0.0 1b2e1d63ff</code><br />            <i>1b2e1d63ff</i> 是你想要标记的提交 ID 的前 10 位字符。可以使用下列命令获取提交 ID：<br />            <code>git log</code><br />            你也可以使用少一点的提交 ID 前几位，只要它的指向具有唯一性。        </p>    </div>    <a name="checkout-replace"></a>    <div class="scrollblock block-checkout-replace">        <h3>替换本地改动-你的后悔药</h3>        <p>            假如你操作失误（当然，这最好永远不要发生），你可以使用如下命令替换掉本地改动：<br />            <code>git checkout -- &lt;filename&gt;</code><br />            此命令会使用 HEAD 中的最新内容替换掉你的工作目录中的文件。已添加到暂存区的改动以及新文件都不会受到影响。        </p>        <p>            假如你想丢弃你在本地的所有改动与提交，可以到服务器上获取最新的版本历史，并将你本地主分支指向它：<br />            <code>git fetch origin</code><br />            <code>git reset --hard origin/master</code>        </p>    </div>    <a name="hints"></a>    <div class="scrollblock block-hints">        <h3>实用小贴士-送你拿去不谢</h3>        <p>            内建的图形化 git：<br />            <code>gitk</code><br />            彩色的 git 输出：<br />            <code>git config color.ui true</code><br />            显示历史记录时，每个提交的信息只显示一行：<br />            <code>git config format.pretty oneline</code><br />            交互式添加文件到暂存区：<br />            <code>git add -i</code>        </p>    </div>    <a name="resources"></a>    <div class="scrollblock block-resources">        <h3>图形化客户端-这个好用</h3>        <p>            <ul>                <li><a href="http://gitx.laullon.com/">GitX (L) (OSX, 开源软件)</a></li>                <li><a href="http://www.git-tower.com/">Tower (OSX)</a></li>                <li><a href="http://www.sourcetreeapp.com/">Source Tree (OSX, 免费)</a></li>                <li><a href="http://mac.github.com/">GitHub for Mac (OSX, 免费)</a></li>                <li><a href="https://itunes.apple.com/gb/app/gitbox/id403388357?mt=12">GitBox (OSX, App Store)</a></li>            </ul>        </p>        <h3>指南和手册-费劲八力收集的</h3>        <p>            <ul>                <li><a href="http://book.git-scm.com/">Git 社区参考书</a></li>                <li><a href="http://progit.org/book/">专业 Git</a></li>                <li><a href="http://think-like-a-git.net/">像 git 那样思考</a></li>                <li><a href="http://help.github.com/">GitHub 帮助</a></li>                <li><a href="http://marklodato.github.io/visual-git-guide/index-zh-cn.html">图解 Git</a></li>            </ul>        </p>    </div>   <div style="display:none;">    <script>var _hmt = _hmt || [];(function() {  var hm = document.createElement("script");  hm.src = "https://hm.baidu.com/hm.js?3eec0b7da6548cf07db3bc477ea905ee";  var s = document.getElementsByTagName("script")[0];   s.parentNode.insertBefore(hm, s);})();</script>   </div><div id="site-navbar" style="position: absolute; top: -4px; left: -3px; border: 0; z-index: 2000;padding:0;margin:0;"><a href="http://www.runoob.com" title="菜鸟教程" style="background:none;"><img src= "/img/loading.gif" data-lazy-src="/img/return-back.png" style="padding:0;margin:0;border:0; -webkit-box-shadow: none;-moz-box-shadow: none;box-shadow: none;"></a></div>   </body></html>]]></content>
      
      
      
        <tags>
            
            <tag> summer </tag>
            
            <tag> Git </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>github开源项目协同开发流程</title>
      <link href="git/github-develop-process/"/>
      <url>git/github-develop-process/</url>
      
        <content type="html"><![CDATA[<h3 id="合作完成开源项目流程"><a href="#合作完成开源项目流程" class="headerlink" title="合作完成开源项目流程"></a>合作完成开源项目流程</h3><ol><li>首先需要在github上注册账号并登陆</li><li>安装git，到github官网下载安装包。</li><li>为github账号添加ssh key</li><li>fork你想参加的项目</li><li>clone项目到本地</li><li>将项目原地址添加为远程仓库</li><li>创建branch，用于添加自己的修改</li><li>同步远程仓库</li><li>将修改push到我们的github上</li><li>pull request</li></ol><h3 id="关键说明"><a href="#关键说明" class="headerlink" title="关键说明"></a>关键说明</h3><p>详细内容，大家可以参考<a href="https://ttk1907.gitee.io/">天凯同学的博客</a>中的<a href="https://ttk1907.gitee.io/2019/08/20/kaiyuan-project-try/">开源项目参加流程</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>git生成SSH并提交</title>
      <link href="git/github-generate-ssh/"/>
      <url>git/github-generate-ssh/</url>
      
        <content type="html"><![CDATA[<h3 id="1-生成秘钥"><a href="#1-生成秘钥" class="headerlink" title="1. 生成秘钥"></a>1. 生成秘钥</h3><p>$ <code>ssh-keygen -t rsa -C &quot;victorfm@163.com&quot; </code><br>按3个回车，密码为空这里一般不使用密钥。<br>最后得到了两个文件：id_rsa和id_rsa. pub 在 ～下的.ssh文件夹中 </p><h3 id="2-查看秘钥"><a href="#2-查看秘钥" class="headerlink" title="2. 查看秘钥"></a>2. 查看秘钥</h3><p><code>cat ~/.ssh/id_rsa.pub  </code><br>复制终端中的秘钥，第四部需要用到</p><h3 id="3-添加私密钥到ssh"><a href="#3-添加私密钥到ssh" class="headerlink" title="3. 添加私密钥到ssh"></a>3. 添加私密钥到ssh</h3><p><code>ssh-add ~/.ssh/id_rsa</code><br>需要之前输入密码（如果有）。</p><h3 id="4-在github上添加ssh密钥"><a href="#4-在github上添加ssh密钥" class="headerlink" title="4. 在github上添加ssh密钥"></a>4. 在github上添加ssh密钥</h3><p>这要添加的是“id_rsa.pub”里面的公钥。<br>在第二步中，将复制下来的结果粘贴到<br>设置–》部署秘钥–》添加部署秘钥  </p><h3 id="5-克隆SSH协议的存储库"><a href="#5-克隆SSH协议的存储库" class="headerlink" title="5. 克隆SSH协议的存储库"></a>5. 克隆SSH协议的存储库</h3><p><code>git clone git@github.com:/victorfengming.github.io.git</code><br>后面根据用户名不同，ssh协议下的url也不一样</p><h3 id="6-推他就完了"><a href="#6-推他就完了" class="headerlink" title="6. 推他就完了"></a>6. 推他就完了</h3><p>git add –all<br>git commit -m”SSH有瑕疵“<br>git push -u origin master<br>到这里可以发现无需输入密码即可将本地的已提交内容推送到服务端</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PHP的特点小结</title>
      <link href="php/php-grammer-sum/"/>
      <url>php/php-grammer-sum/</url>
      
        <content type="html"><![CDATA[<h3 id="语法特点小结-对比python"><a href="#语法特点小结-对比python" class="headerlink" title="语法特点小结(对比python)"></a>语法特点小结(对比python)</h3><ol><li>PHP的变量开头要加上<code>$</code>符号,见到<code>$</code>就知道这个是一个变量</li><li>PHP中的常量才是不用加<code>$</code>符号的</li><li>PHP中$可以用来嵌套使用,从而实现动态的变量名的层级调用</li><li>PHP程序<code>&lt;?php</code>开头,结尾可以加上<code>?&gt;</code>,也可以不加</li><li>PHP中的常量有着魔术常量(系统自带的)</li><li>PHP每行代码最后要有; 除了最后一行代码可以省略外</li><li>PHP中的”双引号”和’单引号’的意义不太一样,其中双引号中可以写变量名,如果变量和字符串相混合写的话,最好用{}符号将变量括起来,更加的规范,也可以增强程序代码的易读性. </li><li>在PHP中,通过对象访问成员属性和成员方法的时候不是用. 而是用-&gt;来调用</li><li>在PHP中,变量的作用域机制十分严格,函数内部不能访问全局的变量</li><li>PHP执行不需要单独的解释器,带有数据库的服务器即可运行php代码</li><li>PHP中用户定义的函数和语言关键字对大小写不敏感。但是变量名区分大小写</li><li>在 PHP 中，不区分大小写的关键字 NULL 用于没有定义值的情况。</li><li>字符串文 0 是转换为布尔值的特殊情况，它转换为 false。</li><li>这条就比较NB了,PHP中的数组,能够自己指定键的值,还TM能省略,让系统自动填,然后就混在一起</li><li>这个更坑,PHP的三目运算符是左结合性的</li><li>数值字符串作为整数进行比较。</li><li>PHP 变量只有一个作用域(函数中除外)</li><li>PHP中\能转义成,在单引号中\n不能换行,在双引号中\n可以转义为换行</li><li>PHP个垃圾语言,不能多继承类</li><li>PHP中是字典类型的数组 不用: 而用<code>=&gt;</code><br>. . . </li></ol>]]></content>
      
      
      
        <tags>
            
            <tag> background </tag>
            
            <tag> php </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PHP中的魔术常量</title>
      <link href="php/php-magic-constant/"/>
      <url>php/php-magic-constant/</url>
      
        <content type="html"><![CDATA[<h3 id="魔术常量"><a href="#魔术常量" class="headerlink" title="魔术常量"></a>魔术常量</h3><p>PHP 向它运行的任何脚本提供了大量的预定义常量。不过很多常量都是由不同的扩展库定义的，只有在加载了这些扩展库时才会出现，或者动态加载后，或者在编译时已经包括进去了。 </p><p>有八个魔术常量它们的值随着它们在代码中的位置改变而改变。例如<code>__LINE__</code>的值就依赖于它在脚本中所处的行来决定。这些特殊的常量不区分大小写，如下： </p><h3 id="几个-PHP-的”魔术常量”"><a href="#几个-PHP-的”魔术常量”" class="headerlink" title="几个 PHP 的”魔术常量”"></a>几个 PHP 的”魔术常量”</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">__LINE__ 文件中的当前行号。  </span><br><span class="line">__FILE__ 文件的完整路径和文件名。如果用在被包含文件中，则返回被包含的文件名。自 PHP 4.0.2 起，__FILE__ 总是包含一个绝对路径（如果是符号连接，则是解析后的绝对路径），而在此之前的版本有时会包含一个相对路径。  </span><br><span class="line">__DIR__ 文件所在的目录。如果用在被包括文件中，则返回被包括的文件所在的目录。它等价于 dirname(__FILE__)。除非是根目录，否则目录中名不包括末尾的斜杠。（PHP 5.3.0中新增） &#x3D;  </span><br><span class="line">__FUNCTION__ 函数名称（PHP 4.3.0 新加）。自 PHP 5 起本常量返回该函数被定义时的名字（区分大小写）。在 PHP 4 中该值总是小写字母的。  </span><br><span class="line">__CLASS__ 类的名称（PHP 4.3.0 新加）。自 PHP 5 起本常量返回该类被定义时的名字（区分大小写）。在 PHP 4 中该值总是小写字母的。类名包括其被声明的作用区域（例如 Foo\Bar）。注意自 PHP 5.4 起 __CLASS__ 对 trait 也起作用。当用在 trait 方法中时，__CLASS__ 是调用 trait 方法的类的名字。  </span><br><span class="line">__TRAIT__ Trait 的名字（PHP 5.4.0 新加）。自 PHP 5.4 起此常量返回 trait 被定义时的名字（区分大小写）。Trait 名包括其被声明的作用区域（例如 Foo\Bar）。  </span><br><span class="line">__METHOD__ 类的方法名（PHP 5.0.0 新加）。返回该方法被定义时的名字（区分大小写）。  </span><br><span class="line">__NAMESPACE__ 当前命名空间的名称（区分大小写）。此常量是在编译时定义的（PHP 5.3.0 新增）。  </span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> background </tag>
            
            <tag> php </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>git版本的回滚</title>
      <link href="git/github-Rollback/"/>
      <url>git/github-Rollback/</url>
      
        <content type="html"><![CDATA[<h3 id="版本出错之解决方法"><a href="#版本出错之解决方法" class="headerlink" title="版本出错之解决方法"></a>版本出错之解决方法</h3><p>很多小伙伴在进行版本控制的时候，有可能会遇到项目不能正常的上传，导致github还是将你最后一个正常push的版本展示出来<br>这时候我们如果想要继续修改，则需要将版本回滚到还没出错的最后一个版本之前才行<br>下面我们介绍一下如何进行版本的回退</p><h5 id="版本回退"><a href="#版本回退" class="headerlink" title="版本回退"></a>版本回退</h5><p>git能够回到任意你提交过的版本，这样对于版本的控制将会十分的方便   ！<br>下面介绍两种方法进行回滚</p><h5 id="github官方的存储库"><a href="#github官方的存储库" class="headerlink" title="github官方的存储库"></a>github官方的存储库</h5><p>你可以在github的存储库中找会对应版本，下载对应的压缩包，</p><h5 id="终端中的git命令"><a href="#终端中的git命令" class="headerlink" title="终端中的git命令"></a>终端中的git命令</h5><p>当然，你也可以使用命令进行，具体命令如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">回退到某个版本（最后的一串字符是 版本变更编号，通常这个编号可以在 git 后台看到，也可以通过  $ git log -300 显示最近300次提交记录）</span><br><span class="line">git reset --hard 目标版本的哈希值 </span><br><span class="line">强制提交到master分支（具体哪个分支请酌情修改）</span><br><span class="line"></span><br><span class="line">git push -f -u origin master</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>git工具基础</title>
      <link href="git/progit-note-first/"/>
      <url>git/progit-note-first/</url>
      
        <content type="html"><![CDATA[<!-- # git工具起步 --><h3 id="关于版本控制"><a href="#关于版本控制" class="headerlink" title="关于版本控制"></a>关于版本控制</h3><p>版本控制是一种记录一个或若干文件内容变化，以便将来查阅特定版本修订情况的系统。</p><h3 id="本地版本控制系统"><a href="#本地版本控制系统" class="headerlink" title="本地版本控制系统"></a>本地版本控制系统</h3><p>版本控制在开发中都是不可避免的问题，最简单的常规方法是通过拷贝整个项目进行控制以及更改，但是这种方法会存在这很多弊端<br>比如说，多人协同工作开发过程中版本的合并问题，找回历史版本的时候有可能会混淆各个版本之间的改动的区别。<br>就算你加上了修改的时间作为项目的名称还是有点瑕疵的<br><br><br>这时候，为了解决这个问题，好早以前就开发了许多种本地版本控制系统，大多都是采用某种简单的数据库来记录文件的历次更新差异<br><br><br><img src= "/img/loading.gif" data-lazy-src="https://gitee.com/progit/figures/18333fig0101-tn.png"><br><br><br>比如有一种叫做rcs，说白了就是保存并管理文件补丁（patch）。<br>文件补丁是一种特定格式的文本文件，记录着对应文件修订前后的内容变化。<br>所以，根据每次修订后的补丁，rcs可以通过不断打补丁，计算出各个版本的文件内容。</p><h3 id="集中化的版本控制系统"><a href="#集中化的版本控制系统" class="headerlink" title="集中化的版本控制系统"></a>集中化的版本控制系统</h3><p>但是现在会出现一个问题，就是说我要是在本地管理我的版本的时候，只能我自己用，如果多人协同开发就费劲了<br>于是，集中化的版本控制系统CVCS应运而生。这种系统的话，都带着一个单一的集中管理的服务器，用于保存所有文件的修订版本，而协同工作的人们都通过客户端连到这台服务器，取出最新的文件或者提交更新，这样就使用起来十分方便了。到现在，这已成为版本控制系统的标准做法（见图 1-2）。<br><br><br><img src= "/img/loading.gif" data-lazy-src="https://gitee.com/progit/figures/18333fig0102-tn.png"><br><br><br>这种方式好处很多，比如任何人都可以在修改项目的时候能够看到其他人都在修改什么，管理员可以方便管理每个人的修改权限，而且维护服务端也比本地端的更加方便<br><br><br>但是这种方式也有点缺点，就是如果服务器的磁盘出现故障，最坏会导致整个项目全部丢失，而这时本地端可能会没有全部的项目来进行恢复的<br>而git的clone方式，会解决这个问题，因为git的克隆操作会将服务端的项目所有记录到本地化。</p><h3 id="分布版本控制"><a href="#分布版本控制" class="headerlink" title="分布版本控制"></a>分布版本控制</h3><p>这种就是现在主流的类型了，git就是最具有代表性的</p><h3 id="协议"><a href="#协议" class="headerlink" title="协议"></a>协议</h3><p>本地协议<br>SSH 协议<br>Git 协议<br>HTTP/S 协议</p><h3 id="有用的链接地址"><a href="#有用的链接地址" class="headerlink" title="有用的链接地址"></a>有用的链接地址</h3><p><a href="https://www.cnblogs.com/kuyuecs/p/7111749.html">git checkout 命令详解</a><br><a href="https://www.cnblogs.com/metoy/p/4097001.html">参与github上开源项目的大致流程和注意事项</a><br><a href="https://www.cnblogs.com/yangshifu/p/9919817.html">Git SSH公钥配置</a><br><a href="https://www.cnblogs.com/superGG1990/p/6844952.html">初次使用git配置以及git如何使用ssh密钥（将ssh密钥添加到github）</a><br><a href="https://www.cnblogs.com/leilei0327/p/8688244.html">github上分支的合并</a><br><a href="https://www.cnblogs.com/metoy/p/4097001.html">参与github上开源项目的大致流程和注意事项</a><br><a href="https://www.yiibai.com/git/git_fetch.html">git fetch命令</a><br><a href="https://blog.csdn.net/shimazhuge/article/details/52759429">git 醉拳版本</a><br><a href="https://blog.csdn.net/weixin_39220472/article/details/82712490">git 最全命令</a><br><a href="https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%8F%98%E5%9F%BA">Git-分支-变基</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> Git </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>markdown简识</title>
      <link href="linux/markdown-easy/"/>
      <url>linux/markdown-easy/</url>
      
        <content type="html"><![CDATA[<ul><li>目录<br>{:toc}</li></ul><!-- # markdown简识 --><h3 id="MarkDown-概述"><a href="#MarkDown-概述" class="headerlink" title="MarkDown 概述"></a>MarkDown 概述</h3><p>Markdown是一种可以使用普通文本编辑器编写的标记语言，通过简单的标记语法，它可以使普通文本内容具有一定的格式。</p><p>Markdown 语言在 2004 由约翰·格鲁伯（英语：John Gruber）创建。</p><p>Markdown 编写的文档可以导出 HTML 、Word、图像、PDF、Epub 等多种格式的文档。</p><p>Markdown 编写的文档后缀为 .md, .markdown。</p><p>Markdown具有一系列衍生版本，用于扩展Markdown的功能（如表格、脚注、内嵌HTML等等），这些功能原初的Markdown尚不具备，它们能让Markdown转换成更多的格式，例如LaTeX，Docbook。Markdown增强版中比较有名的有Markdown Extra、MultiMarkdown、 Maruku等。这些衍生版本要么基于工具，如Pandoc；要么基于网站，如GitHub和Wikipedia，在语法上基本兼容，但在一些语法和渲染效果上有改动。</p><h3 id="Markdown-应用"><a href="#Markdown-应用" class="headerlink" title="Markdown 应用"></a>Markdown 应用</h3><p>Markdown 能被使用来撰写电子书，如：Gitbook。</p><p>当前许多网站都广泛使用 Markdown 来撰写帮助文档或是用于论坛上发表消息。例如：GitHub、简书、reddit、Diaspora、Stack Exchange、OpenStreetMap 、SourceForge等。</p><h3 id="Markdown-编辑器"><a href="#Markdown-编辑器" class="headerlink" title="Markdown 编辑器"></a>Markdown 编辑器</h3><p>大家可以使用任意的能够编辑文本文档的编辑器来编辑它，因为markdown只是一种文档格式</p><p>这里大家可以参考： <a href="https://blog.csdn.net/bat67/article/details/72804251">整理：几款好用的Markdown编辑器</a></p><h3 id="Markdown-查看器"><a href="#Markdown-查看器" class="headerlink" title="Markdown 查看器"></a>Markdown 查看器</h3><p>这里小编推荐大家使用Typora</p><p>Typora 支持 MacOS 、Windows、Linux 平台，且包含多种主题，编辑后直接渲染出效果。</p><p>支持导出HTML、PDF、Word、图片等多种类型文件。</p><p>Typora 官网：<a href="https://typora.io/">https://typora.io/</a></p><h3 id="最最关键的部分"><a href="#最最关键的部分" class="headerlink" title="最最关键的部分"></a>最最关键的部分</h3><p><a href="https://ttk1907.gitee.io/">天凯同学</a>整理的markdown的一些demo</p><p>由于他写的比较全面，这里小编就给出他的链接供大家学习参考</p><p><a href="https://ttk1907.gitee.io/2019/08/16/markdown-to-application/">Markdown实例</a></p><p>大家可以去参考参考，也可以关注他</p><h3 id="demo"><a href="#demo" class="headerlink" title="demo"></a>demo</h3><h1 id="我展示的是一级标题"><a href="#我展示的是一级标题" class="headerlink" title="我展示的是一级标题"></a>我展示的是一级标题</h1><h2 id="我展示的是二级标题"><a href="#我展示的是二级标题" class="headerlink" title="我展示的是二级标题"></a>我展示的是二级标题</h2><table><thead><tr><th align="left">左对齐</th><th align="right">右对齐</th><th align="center">居中对齐</th></tr></thead><tbody><tr><td align="left">单元格</td><td align="right">单元格</td><td align="center">单元格</td></tr><tr><td align="left">单元格</td><td align="right">单元格</td><td align="center">单元格</td></tr></tbody></table><ul><li>第一项</li><li>第二项</li><li>第三项</li></ul><ul><li>第一项</li><li>第二项</li><li>第三项</li></ul><ul><li>第一项</li><li>第二项</li><li>第三项</li></ul><blockquote><p>最外层</p><blockquote><p>第一层嵌套</p><blockquote><p>第二层嵌套</p></blockquote></blockquote></blockquote><blockquote><p>区块中使用列表</p><ol><li>第一项</li><li>第二项</li></ol><ul><li>第一项</li><li>第二项</li><li>第三项</li></ul></blockquote><blockquote><p>one indee<br>one index</p><blockquote><blockquote><p>third index</p><blockquote><p>fouth index</p></blockquote></blockquote></blockquote></blockquote><ul><li>第一项<blockquote><p>菜鸟教程<br>学的不仅是技术更是梦想</p></blockquote></li><li>第二项</li></ul><p><em>斜体文本</em><br><em>斜体文本</em><br><strong>粗体文本</strong><br><strong>粗体文本</strong><br><em><strong>粗斜体文本</strong></em><br><em><strong>粗斜体文本</strong></em></p><p>ZHENGTI<a href="%E6%AD%A3%E6%8C%BA%E5%A5%BD">^1</a>NGHAO  </p><p>创建脚注格式类似这样 [^RUNOOB]。</p><p>[^RUNOOB]: 菜鸟教程 – 学的不仅是技术，更是梦想！！！</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>,<span class="number">100</span>):</span><br><span class="line">    print(i)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span>(<span class="params">self</span>):</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> basis </tag>
            
            <tag> skills </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Notepad++运行python</title>
      <link href="ide/notepad-run-python/"/>
      <url>ide/notepad-run-python/</url>
      
        <content type="html"><![CDATA[<h3 id="关于使用notepad运行python程序"><a href="#关于使用notepad运行python程序" class="headerlink" title="关于使用notepad运行python程序"></a>关于使用notepad运行python程序</h3><ol><li>首先要确保python解释器已经安装成功,查看方法,windows可以在命令提示符中查看,通过按下win+R键,调出运行窗口,在输入框中输入cmd回车,然后在命令行中输入python,若出现版本信息,例如<code>Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32 Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.</code>则安装成功,若出现<code>&#39;python&#39; 不是内部或外部命令，也不是可运行的程序</code>,则需要配置环境变量,详情参考<a href="https://blog.csdn.net/taowuhua0505/article/details/80435374">如何配置python的环境变量</a></li><li>在在notepad++中，按F5，或者菜单栏点击 “运行－＞运行” (默认快捷键是 F5 )，在弹出的对话框中，输入<code>cmd /k python &quot;$(FULL_CURRENT_PATH)&quot;&amp; PAUSE &amp; EXIT</code></li></ol><div align="center">    <img src= "/img/loading.gif" data-lazy-src="/img/posts/technology/20190712173112386notepad1.png" >  </div><ol start="3"><li>点击 “保存”，就可以给这条命令设置一个快捷键并起一个名字，比如 “run_python”。以后运行直接按自定义的快捷键就妥了。</li></ol> <div align="center">    <img src= "/img/loading.gif" data-lazy-src="/img/posts/technology/20190712173148840notepad2.png" >  </div>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>PyCharm的安装以及破解</title>
      <link href="ide/jetbrains/pycharm/pycharm-install/"/>
      <url>ide/jetbrains/pycharm/pycharm-install/</url>
      
        <content type="html"><![CDATA[<ul><li>目录<br>{:toc}</li></ul><h2 id="PyCharm"><a href="#PyCharm" class="headerlink" title="PyCharm"></a>PyCharm</h2><p>PyCharm是一种Python IDE，带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具，比如调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外，该IDE提供了一些高级功能，以用于支持Django框架下的专业Web开发。</p><h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>对于很多学习python的小伙伴,一个优秀的编辑器可以提高你code的速度,让你专注于思维逻辑的思考,本篇文章小编就介绍一下如何安装和破解PyCharm编辑器.<br>首先,没有安装python环境的同学需要先去看一下<a href="https://blog.csdn.net/qq_40223983/article/details/95655470">python安装以及版本检测</a><br>我们需要进入到jetbrains公司的<a href="http://www.jetbrains.com/pycharm/download/">官网下载地址</a>下载安装包<br>这里面分为两个版本,一个是免费的社区版本,另一是收费的专业版本.对于一些初学者,可以先安装一个社区版本练手,对于稍微有点儿基础的同学,可以下载专业版本,毕竟专业版本的功能更加丰富.</p><h3 id="安装PyCharm"><a href="#安装PyCharm" class="headerlink" title="安装PyCharm"></a>安装PyCharm</h3><p>下载安装包,可以在<a href="http://www.jetbrains.com/pycharm/?fromMenu">PyCharm官网</a>下载安装包  </p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install1.png" alt="img description">h<br>下载好安装包后,双击即可打开<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install2.png" alt="img description"><br>打开后点击next<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install3.png" alt="img description"><br>下面是选择安装的路径,这里我们放在D盘中<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install4.png" alt="img description"><br>这里我们需要勾选安装软件的位数,如何查看自己计算机位数,可以参考<a href="https://blog.csdn.net/a_dreaming_fish/article/details/50442617">查看计算机位数以及操作系统位数</a>,选择自己对应的版本即可,后面create Associations是创建文件自动添加扩展名的,这里我们可以勾上,然后点击next<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install5.png" alt="img description"></p><p>这里点击install<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install6.png" alt="img description"><br>去喝一杯咖啡等待一下<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install7.png" alt="img description"><br>这样就安装好了,我们直接点击Finsh,就完成了PyCharm的安装<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install8.png" alt="img description"></p><h3 id="破解PyCharm"><a href="#破解PyCharm" class="headerlink" title="破解PyCharm"></a>破解PyCharm</h3><p>PyCharm安装成功后,我们在桌面会发现一个快捷方式,双击打开<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install9.png" alt="img description"><br>打开后,这里需要让我们选择导入PyCharm的设置,可以下载<a href="https://download.csdn.net/download/qq_40223983/11367284">PyCharm设置文件</a>对于第一次用的宝宝们,直接勾选下面的不导入设置,点击OK<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install10.png" alt="img description"><br>这里让我们选择PyCharm的主题风格,宝宝们可以根据自己的喜好来选择,这里我们选择深色主题,点击Next<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install11.png" alt="img description"><br>这里提示我们安装一些插件,我们直接跳过即可,点击start using PyCharm 开始使用<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install12.png" alt="img description"><br>这里需要我们填写破解信息<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install13.png" alt="img description"><br>小编给大家提供了一个网站<a href="http://idea.medeming.com/jet/">IntlliJ IDEA注册码</a>  </p><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install14.png" alt="img description"><br>点击获得注册码<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install15.png" alt="img description"><br>复制注册码到剪切板,但是在这之前还需要清除host文件中屏蔽的网址<br>在C:\Windows\System32\drivers\etc目录中有一个名为host的文件<br>右键选择打开方式<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install16.png" alt="img description"><br>这里我们选择记事本打开,打开后将下面这两行代码粘贴到文件尾部,保存即可  </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">0.0.0.0 account.jetbrains.com</span><br><span class="line">0.0.0.0 www.jetbrains.com</span><br></pre></td></tr></table></figure><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install17.png" alt="img description"><br>下面我们回到<a href="http://idea.lanyus.com/">IntelliJ IDEA 注册码  </a><br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install18.png" alt="img description"><br>复制注册码后,在PyCharm中选中Activation code 粘贴<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install19.png" alt="img description"><br>这里需要将注册码前面的文字部分删除掉,然后注册码会变成绿色,如图所示<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install20.png" alt="img description"><br>直接点击OK,出现这个界面说明PyCharm破解成功<br><img src= "/img/loading.gif" data-lazy-src="/img/posts/pycharm/install21.png" alt="img description"><br>到这里PyCharm的安装和破解过程就完成了,如何使用这个编辑器以及使用的一些小技巧,请关注小编后面的内容。</p>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> pycharm </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>vim编辑器简介</title>
      <link href="linux/vim/"/>
      <url>linux/vim/</url>
      
        <content type="html"><![CDATA[<h3 id="vim编辑器简介"><a href="#vim编辑器简介" class="headerlink" title="vim编辑器简介"></a>vim编辑器简介</h3><h3 id="Linux-vi-vim"><a href="#Linux-vi-vim" class="headerlink" title="Linux vi/vim"></a>Linux vi/vim</h3><p>所有的 Unix Like 系统都会内建 vi 文书编辑器，其他的文书编辑器则不一定会存在。</p><p>但是目前我们使用比较多的是 vim 编辑器。</p><p>vim 具有程序编辑的能力，可以主动的以字体颜色辨别语法的正确性，方便程序设计。</p><h3 id="什么是-vim？"><a href="#什么是-vim？" class="headerlink" title="什么是 vim？"></a>什么是 vim？</h3><p>Vim是从 vi 发展出来的一个文本编辑器。代码补完、编译及错误跳转等方便编程的功能特别丰富，在程序员中被广泛使用。</p><p>简单的来说， vi 是老式的字处理器，不过功能已经很齐全了，但是还是有可以进步的地方。 vim 则可以说是程序开发者的一项很好用的工具。</p><p>连 vim 的<a href="http://www.vim.org/">官方网站www.vim.org</a> 自己也说 vim 是一个程序开发工具而不是文字处理软件。</p><h3 id="vi-vim-的使用模式"><a href="#vi-vim-的使用模式" class="headerlink" title="vi/vim 的使用模式"></a>vi/vim 的使用模式</h3><p>基本上 vi/vim 共分为三种模式，分别是命令模式（Command mode），输入模式（Insert mode）和底线命令模式（Last line mode）。</p><img src= "/img/loading.gif" data-lazy-src="https://www.runoob.com/wp-content/uploads/2015/10/vi-vim-cheat-sheet-sch.gif"><p>由于小编也是刚刚接触使用vim，所以这里给大家提供一些比较全教程链接</p><p><a href="https://blog.csdn.net/yangshuainan/article/details/78219604">CSDN -&gt; linux 下vim的使用（学习必看！！重要）</a></p><p><a href="https://www.runoob.com/linux/linux-vim.html">菜鸟教程 -&gt; Linux vi/vim </a></p><p><a href="https://www.cnblogs.com/lijia0511/p/5644566.html">博客园 -&gt; vim简单使用教程 </a></p>]]></content>
      
      
      
        <tags>
            
            <tag> Linux </tag>
            
            <tag> basis </tag>
            
            <tag> vim </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>送你一些小技巧</title>
      <link href="unclass/various-skills/"/>
      <url>unclass/various-skills/</url>
      
        <content type="html"><![CDATA[<p><img src= "/img/loading.gif" data-lazy-src="/img/assets/dubbo/spring-cloud/Spring-Cloue-Zookeeper.png" alt="img/assets/dubbo/spring-cloud"><br><img src= "/img/loading.gif" data-lazy-src="img/assets/dubbo/spring-cloud/Spring-Cloue-Zookeeper.png" alt="img/assets/dubbo/spring-cloud"><br><img src= "/img/loading.gif" data-lazy-src="/assets/dubbo/spring-cloud/Spring-Cloue-Zookeeper.png" alt="/assets/dubbo/spring-clou"><br><img src= "/img/loading.gif" data-lazy-src="!--swig%EF%BF%BC0--" alt="图片pic1"></p><h3 id="这里总结一些关于平时的边边角角的一些小技巧吧"><a href="#这里总结一些关于平时的边边角角的一些小技巧吧" class="headerlink" title="这里总结一些关于平时的边边角角的一些小技巧吧"></a>这里总结一些关于平时的边边角角的一些小技巧吧</h3><p>可能这些东西你会，也可能你觉得这些不是很正常的东西么，甚至你想说这也能往上面写</p><p>小编的这些小技巧仅仅个人总结，如有了解，请忽略它们，这里是仅仅给一些小白的经验。</p><p>目前还没有多少的内容，但是随着小编逐渐的学习过程，会慢慢的补充上去，请持续关注！</p><h3 id="命令技巧"><a href="#命令技巧" class="headerlink" title="命令技巧"></a>命令技巧</h3><ol><li><a href="https://1978413822.github.io/">岳阳</a>说：    你这个：+ wq保存的不够快<br> 在vim编辑器中的编辑模式中，直接按下esc键，输入大写的ZZ直接退出，并且保存了文件</li></ol><h3 id="代码技巧"><a href="#代码技巧" class="headerlink" title="代码技巧"></a>代码技巧</h3><p>小换行：Pycharm中的shift+Enter</p><h3 id="系统相关"><a href="#系统相关" class="headerlink" title="系统相关"></a>系统相关</h3><h3 id="快捷键技巧"><a href="#快捷键技巧" class="headerlink" title="快捷键技巧"></a>快捷键技巧</h3><ol><li><p><a href="https://ttk1907.gitee.io/">ttk1907</a>问：        你是怎么往后删的？</p><p> 答：</p><pre><code> Backspace往前面删除  Delete可以将代码往后删除</code></pre></li><li><p><a href="https://nineberg.github.io/">nineberg</a>问：        我写代码慢，比如html标签，有什么快速的方法么？</p><p> 答：</p><pre><code> 在sublime中可以利用tab键自动补全html标签 不仅编辑器中可以这样，比如说我们在终端中敲命令后执行的文件，也可以使用tab键快速补全</code></pre></li><li><p><a href="https://ttk1907.gitee.io/">ttk1907</a>问：        怎么才能在终端中输入之前输入的命令        </p><p> 答：</p><pre><code> 你之前输入成功的命令 按方向键中的上下即可快速调出历史命令</code></pre></li><li><p><a href="https://caoyang7.github.io/">caoyang7</a>说:<br> sublime中<code>ctrl+H</code>他就能查找还能替换呢，就像pycharm中的<code>Ctrl+R</code>一样</p></li><li><p><a href="https://caoyang7.github.io/">caoyang7</a>说:<br> Ubuntu的终端中Ctrl+shift+‘+’能够进行字体的放大，Ctrl+‘-’能够减小字体  </p></li></ol><h3 id="其他不太会分类的"><a href="#其他不太会分类的" class="headerlink" title="其他不太会分类的"></a>其他不太会分类的</h3><ol><li><p><a href="https://ttk1907.gitee.io/">ttk1907</a>问：        init是啥玩意<br> 答：</p><pre><code> init是initial的简单写法 它能够标记出当前的文件夹为一种特定格式 比如说，在python中，如果这个文件夹中有__init__.py这个文件，那么就代表这个文件夹是一个python可识别的package包 在举一个栗子，在git中，如果执行git init，会在当前文件夹中生成一个名字为.git的隐藏文件夹，用于存储git的版本信息</code></pre></li><li><p><a href="https://caoyang7.github.io/">caoyang7</a>问，在Linux中html中还能直接拖进浏览器呢啊？<br> 答：</p><pre><code> 那当然能了   window也能</code></pre></li><li><p><a href="https://caoyang7.github.io/">caoyang7</a>问，chrome浏览器中居然还能看手机的样式？<br> 答：</p><pre><code> 哇塞这个太厉害了，我的天呐！ 不仅能预览手机模式，还能选择手机型号，整挺好！  </code></pre><p><img src= "/img/loading.gif" data-lazy-src="/img/posts/technology/chrome-phone.png" alt="imgdes">    </p></li></ol><br>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> skills </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Ubuntu系统的安装</title>
      <link href="linux/ubuntu-install/"/>
      <url>linux/ubuntu-install/</url>
      
        <content type="html"><![CDATA[<h2 id="一、-安装版本"><a href="#一、-安装版本" class="headerlink" title="一、 安装版本"></a>一、 安装版本</h2><p>这里我们选择的是ubuntu18版本,虽然现在最新版本的已经有Ubuntu19.04了,但是我们这个Ubuntu 18版本更加的稳定,相对来说可能遇到的问题会少一点儿，毕竟稳定版的用户相对数量还是比较大的。</p><h3 id="镜像下载"><a href="#镜像下载" class="headerlink" title="镜像下载"></a>镜像下载</h3><p>首先，我们需要去找到一个ubuntu 的系统的ISO镜像，可以去 <a href="https://cn.ubuntu.com/download">ubuntu的官网下载地址</a> 下载到。<br>这个ISO镜像是包含Ubuntu的系统安装包,下一步我们需要将这个镜像烧录到U盘中。</p><h3 id="启动盘制作"><a href="#启动盘制作" class="headerlink" title="启动盘制作"></a>启动盘制作</h3><p>这里我使用的工具是rufus.exe，这个工具是开源的，可以去 <a href="http://rufus.ie/">官网</a> 进行下载。<br>下载好后，将一个空U盘插到电脑上，在工具中分别选中ISO镜像文件和U盘，点击开始后等待制作完成即可。</p><h5 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h5><p>在制作过程中，工具可能会提示需要联网加载一些镜像的依赖包，保持连网点击确定即可。</p><h3 id="配置BIOS"><a href="#配置BIOS" class="headerlink" title="配置BIOS"></a>配置BIOS</h3><p>这一步，我们需要关机后进入BIOS界面，设置U盘启动项为第一项，在这里每个人的笔记本由于型号不同，可能会有所差异。<br>配置后，即可进入ubuntu系统的安装</p><h3 id="安装系统"><a href="#安装系统" class="headerlink" title="安装系统"></a>安装系统</h3><p>这里设置安装位置，语音，驱动等配置参数<br>等待安装成功即可</p><p>关于双显卡不能进入ubuntu系统的解决方案,可以参考<a href="https://ttk1907.gitee.io/">师哥</a>的<a href="https://ttk1907.gitee.io/2019/08/14/xiongdihui-one-daily/">入坑兄弟会第一天</a>相关内容</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> system </tag>
            
            <tag> Linux </tag>
            
            <tag> ubuntu </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>matplotlib绘图相关</title>
      <link href="python/data_analysis/matplotlib/"/>
      <url>python/data_analysis/matplotlib/</url>
      
        <content type="html"><![CDATA[<h2 id="第一部分"><a href="#第一部分" class="headerlink" title="第一部分"></a>第一部分</h2><h3 id="chapter01-matplotlib和numpy起步"><a href="#chapter01-matplotlib和numpy起步" class="headerlink" title="chapter01 matplotlib和numpy起步"></a>chapter01 matplotlib和numpy起步</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/14 10:39&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 用于测试matplotlib</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="comment"># plt.plot([1,2,3],[3,2,1])</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line">plt.plot([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>],[-<span class="number">4</span>,-<span class="number">3</span>,-<span class="number">2</span>,-<span class="number">1</span>])</span><br><span class="line">plt.show()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">numpy是python开源的数值计算扩展</span></span><br><span class="line"><span class="string">可用来储存和处理大型矩阵,比python自身的数据结构要高效</span></span><br><span class="line"><span class="string">numpy将python变成了一种免费强大的MATLAB系统</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ndarray 创建 一般有三种方式</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">1. 从python的基础数据对象进行转化</span></span><br><span class="line"><span class="string">2. 通过numpy内生成的函数生成</span></span><br><span class="line"><span class="string">3. 从硬盘(文件)读取数据</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 索引和切片(类似于列表的操作)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 常用函数</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">min,max,median,mean,variance,sort</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="chapter02-matplotlib中计算各种值"><a href="#chapter02-matplotlib中计算各种值" class="headerlink" title="chapter02 matplotlib中计算各种值"></a>chapter02 matplotlib中计算各种值</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line">c = np.random.randint(<span class="number">1</span>,<span class="number">100</span>,<span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">print(c)</span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># # 求最大值</span></span><br><span class="line"><span class="comment"># print(np.max(c))</span></span><br><span class="line"><span class="comment"># print(c.max())</span></span><br><span class="line"><span class="comment"># # 求最小值</span></span><br><span class="line"><span class="comment"># print(np.min(c))</span></span><br><span class="line"><span class="comment"># print(c.min())</span></span><br><span class="line"><span class="comment"># # 求均值</span></span><br><span class="line"><span class="comment"># print(np.mean(c))</span></span><br><span class="line"><span class="comment"># print(c.mean())</span></span><br><span class="line"><span class="comment"># # 求方差</span></span><br><span class="line"><span class="comment"># print(np.var(c))</span></span><br><span class="line"><span class="comment"># print(c.var())</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># np.save(&#x27;x.npy&#x27;,c) # 存为.npy文件</span></span><br><span class="line"></span><br><span class="line">c = np.load(<span class="string">&#x27;x.npy&#x27;</span>)</span><br><span class="line">print(c)</span><br></pre></td></tr></table></figure><h3 id="chapter03-matplotlib绘制散点图"><a href="#chapter03-matplotlib绘制散点图" class="headerlink" title="chapter03 matplotlib绘制散点图"></a>chapter03 matplotlib绘制散点图</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/14 11:09&#x27;</span></span><br><span class="line"><span class="string">这回我们来画散点图,散点图最大的特点就是能体现相关性,比如正相关,负相关,和不相关</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 正相关的</span></span><br><span class="line"><span class="comment"># height = [161,172,182,175,173,165]</span></span><br><span class="line"><span class="comment"># weight = [50,58,80,70,69,55]</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># plt.scatter(height,weight)</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 不相关的</span></span><br><span class="line"><span class="comment"># N = 1000</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># x1 = np.random.randn(N)</span></span><br><span class="line"><span class="comment"># y1 = np.random.randn(N)</span></span><br><span class="line"><span class="comment"># plt.scatter(x1,y1)</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 正相关的</span></span><br><span class="line"><span class="comment"># N = 1000</span></span><br><span class="line"><span class="comment"># x1 = np.random.randn(N)</span></span><br><span class="line"><span class="comment"># y1 = x1 + np.random.randn(N)*0.5</span></span><br><span class="line"><span class="comment"># plt.scatter(x1,y1)</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 负相关的</span></span><br><span class="line">N = <span class="number">1000</span></span><br><span class="line">x1 = np.random.randn(N)</span><br><span class="line">y1 = - x1 + np.random.randn(N)*<span class="number">0.5</span></span><br><span class="line">plt.scatter(x1,y1,s=<span class="number">50</span>,alpha = <span class="number">0.5</span>,c=<span class="string">&#x27;r&#x27;</span>,marker=<span class="string">&#x27;&lt;&#x27;</span>)</span><br><span class="line">plt.show()</span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">图表能够十分直观的体现出数据之间的关系,</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 散点图的外观调整</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">1. 颜色 c</span></span><br><span class="line"><span class="string">2. 点大小 s</span></span><br><span class="line"><span class="string">3. 透明度 alpha</span></span><br><span class="line"><span class="string">4. 点形状,marker</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="chapter04-matplotlib绘制折线图"><a href="#chapter04-matplotlib绘制折线图" class="headerlink" title="chapter04 matplotlib绘制折线图"></a>chapter04 matplotlib绘制折线图</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line">x = np.linspace(-<span class="number">10</span>,<span class="number">10</span>,<span class="number">5</span>)</span><br><span class="line">y = x**<span class="number">2</span></span><br><span class="line"></span><br><span class="line">plt.plot(x,y)</span><br><span class="line">plt.show()</span><br><span class="line">```  </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">### chapter05 matplotlib绘制条形图</span></span><br><span class="line"></span><br><span class="line">```python</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/14 14:03&#x27;</span></span><br><span class="line"><span class="string">本节我们来画条形图</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 概念:条形图其实就是使用长方形的长度来显示变量大小的图表</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 用来比较多个数据的大小,通常利于数据集较少的分析</span></span><br><span class="line"><span class="comment"># 例如不同季度的销量,不同国家的人口等yufengmengyufengmengyufengmeng</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line">N = <span class="number">5</span></span><br><span class="line">y = [<span class="number">20</span>,<span class="number">10</span>,<span class="number">30</span>,<span class="number">25</span>,<span class="number">15</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># index = np.arange(N)</span></span><br><span class="line"><span class="comment"># # pl = plt.bar(x=index,height=y,color=&#x27;green&#x27;,width=0.5)</span></span><br><span class="line"><span class="comment"># # pl2 = plt.bar(x=0,bottom=index,width=y,color=&quot;red&quot;,height=0.5,orientation=&quot;horizontal&quot;)</span></span><br><span class="line"><span class="comment"># pl2 = plt.bar(x=0,bottom=index,width=y,color=&quot;red&quot;,height=0.5)</span></span><br><span class="line"><span class="comment"># # pl3 = plt.barh(y=0,width=y,index=index)</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"></span><br><span class="line">index = np.arange(<span class="number">4</span>)</span><br><span class="line"></span><br><span class="line">sales_BJ = [<span class="number">52</span>,<span class="number">55</span>,<span class="number">63</span>,<span class="number">53</span>]</span><br><span class="line">sales_SH = [<span class="number">44</span>,<span class="number">66</span>,<span class="number">55</span>,<span class="number">41</span>]</span><br><span class="line"></span><br><span class="line">bar_width = <span class="number">0.3</span></span><br><span class="line"></span><br><span class="line">plt.bar(index,sales_BJ,bar_width,color=<span class="string">&quot;b&quot;</span>)</span><br><span class="line">plt.bar(index+bar_width,sales_SH,bar_width,color=<span class="string">&quot;r&quot;</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><h3 id="chapter06-matplotlib绘制直方图"><a href="#chapter06-matplotlib绘制直方图" class="headerlink" title="chapter06 matplotlib绘制直方图"></a>chapter06 matplotlib绘制直方图</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/14 17:47&#x27;</span></span><br><span class="line"><span class="string">直方图</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># import numpy as np</span></span><br><span class="line"><span class="comment"># import matplotlib.pyplot as plt</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 直方图是由一系列高度不等的纵向条形组成,表示数据分布情况</span></span><br><span class="line"><span class="comment"># 这里需要注意和条形图区分</span></span><br><span class="line"><span class="comment"># 直方图通常表示连续变化的数据</span></span><br><span class="line"><span class="comment"># 条形图通常用于展示不同类型的数据,而且这个类别通常是不连续的</span></span><br><span class="line"><span class="comment"># 说白了就是直方图,中间没有空</span></span><br><span class="line"><span class="comment"># &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># mu = 100</span></span><br><span class="line"><span class="comment"># sigma = 20</span></span><br><span class="line"><span class="comment"># x = mu+ sigma*np.random.randn(20000)</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># # print(x)</span></span><br><span class="line"><span class="comment"># # plt.hist(x,bins=10)</span></span><br><span class="line"><span class="comment"># &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># The &#x27;normed&#x27; kwarg was deprecated in Matplotlib 2.1 and will be removed in 3.1. Use &#x27;density&#x27; instead.</span></span><br><span class="line"><span class="comment">#   plt.hist(x,bins=10,color=&#x27;red&#x27;,normed=True)</span></span><br><span class="line"><span class="comment">#   &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># # plt.hist(x,bins=50,color=&#x27;green&#x27;,density=True)</span></span><br><span class="line"><span class="comment"># plt.hist(x,bins=500,color=&#x27;green&#x27;)</span></span><br><span class="line"><span class="comment"># # 这里bins表示有几个条装的柱形</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 一个双变量的直方图</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line">x = np.random.randn(<span class="number">1000</span>)+<span class="number">2</span></span><br><span class="line">y = np.random.randn(<span class="number">1000</span>)+<span class="number">3</span></span><br><span class="line"></span><br><span class="line">plt.hist2d(x,y,bins=<span class="number">40</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><h3 id="chapter07-matplotlib绘制饼状图"><a href="#chapter07-matplotlib绘制饼状图" class="headerlink" title="chapter07 matplotlib绘制饼状图"></a>chapter07 matplotlib绘制饼状图</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/14 23:12&#x27;</span></span><br><span class="line"><span class="string">这节我们来练习画饼状图,的饼状图用于显示各项的大小和总和的比例</span></span><br><span class="line"><span class="string">饼状图中的数据点显示为整个饼状图的百分比</span></span><br><span class="line"><span class="string">如前十大品牌占市场份额图</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line">labels = <span class="string">&#x27;A&#x27;</span>,<span class="string">&#x27;B&#x27;</span>,<span class="string">&#x27;C&#x27;</span>,<span class="string">&#x27;D&#x27;</span></span><br><span class="line">fracs = [<span class="number">15</span>,<span class="number">30</span>,<span class="number">45</span>,<span class="number">10</span>]</span><br><span class="line">explode = [<span class="number">0.2</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0.2</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在python2中,好像默认不是正圆,那么要想整成正圆,就要这样写法</span></span><br><span class="line">plt.axes(aspect=<span class="number">1</span>)  <span class="comment"># 这行我就不知道有什么用,感觉是毛用没有啊</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">plt.pie(x=fracs,labels=labels,autopct=<span class="string">&#x27;%.0f%%&#x27;</span>,explode=explode,shadow=<span class="literal">True</span>)</span><br><span class="line"><span class="comment"># 这个autopct是python中的格式化字符串</span></span><br><span class="line"><span class="comment"># explode能够突出显示某几块儿的值</span></span><br><span class="line"><span class="comment"># shadow是阴影</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># pyth&#x27;onpythonpytho&#x27;n python python python pyth&#x27;on python pyhto&#x27;n pythio</span></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">def pie(</span></span><br><span class="line"><span class="string">        x, explode=None, labels=None, colors=None, autopct=None,</span></span><br><span class="line"><span class="string">        pctdistance=0.6, shadow=False, labeldistance=1.1,</span></span><br><span class="line"><span class="string">        startangle=None, radius=None, counterclock=True,</span></span><br><span class="line"><span class="string">        wedgeprops=None, textprops=None, center=(0, 0), frame=False,</span></span><br><span class="line"><span class="string">        rotatelabels=False, *, data=None):</span></span><br><span class="line"><span class="string">    return gca().pie(</span></span><br><span class="line"><span class="string">        &#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">plt.show()</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="chapter08-matplotlib绘制箱型图"><a href="#chapter08-matplotlib绘制箱型图" class="headerlink" title="chapter08 matplotlib绘制箱型图"></a>chapter08 matplotlib绘制箱型图</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/14 23:34&#x27;</span></span><br><span class="line"><span class="string">本节课我们画箱型图</span></span><br><span class="line"><span class="string">箱型图又称之为盒须图,盒式图或者箱线图</span></span><br><span class="line"><span class="string">是一种用作显示一组数据分散情况资料的统计图</span></span><br><span class="line"><span class="string">上边缘,上四分位数,中位数,下四分位数,下边缘,异常值</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line">a = [<span class="number">42</span>,<span class="number">55</span>,<span class="number">79</span>,<span class="number">68</span>,<span class="number">15</span>,<span class="number">98</span>]</span><br><span class="line">b = [<span class="number">32</span>,<span class="number">59</span>,<span class="number">77</span>,<span class="number">100</span>,<span class="number">92</span>,<span class="number">88</span>,<span class="number">5</span>,<span class="number">0</span>]</span><br><span class="line">c = [<span class="number">92</span>,<span class="number">98</span>,<span class="number">78</span>,<span class="number">65</span>,<span class="number">97</span>,<span class="number">100</span>,<span class="number">0</span>]</span><br><span class="line"></span><br><span class="line">plt.boxplot(</span><br><span class="line">    (a,c,b),  <span class="comment"># 数据</span></span><br><span class="line">    labels = (<span class="string">&#x27;a&#x27;</span>,<span class="string">&#x27;c&#x27;</span>,<span class="string">&#x27;b&#x27;</span>),  <span class="comment"># 标签</span></span><br><span class="line"></span><br><span class="line">    showfliers = <span class="literal">True</span>,  <span class="comment"># 是否显示异常值，默认显示</span></span><br><span class="line">    whis = <span class="number">1.5</span>,  <span class="comment"># 指定异常值参数：默认1.5倍四分位差</span></span><br><span class="line">    showmeans = <span class="literal">True</span>, <span class="comment"># 是否显示平均值，默认不显示</span></span><br><span class="line">    meanline = <span class="literal">True</span>, <span class="comment"># 是否用线标示平均值，默认用点</span></span><br><span class="line"></span><br><span class="line">    widths = <span class="number">0.5</span>, <span class="comment"># 柱子宽度</span></span><br><span class="line"></span><br><span class="line">    vert = <span class="literal">True</span>, <span class="comment"># 默认True纵向，False横向</span></span><br><span class="line">    patch_artist = <span class="literal">True</span>,  <span class="comment"># 是否填充颜色</span></span><br><span class="line">    boxprops = &#123;<span class="string">&#x27;facecolor&#x27;</span>:<span class="string">&#x27;#ffff00&#x27;</span>,<span class="string">&#x27;color&#x27;</span>:<span class="string">&#x27;green&#x27;</span>&#125;, <span class="comment"># 箱体样式</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">plt.grid(linewidth=<span class="number">0.2</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><h3 id="chapter09-matplotlib中的颜色"><a href="#chapter09-matplotlib中的颜色" class="headerlink" title="chapter09 matplotlib中的颜色"></a>chapter09 matplotlib中的颜色</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/15 11:29&#x27;</span></span><br><span class="line"><span class="string">这回我们来玩颜色,八种内建颜色缩写</span></span><br><span class="line"><span class="string">    b:blue</span></span><br><span class="line"><span class="string">    g:green</span></span><br><span class="line"><span class="string">    r:red</span></span><br><span class="line"><span class="string">    c:cyan</span></span><br><span class="line"><span class="string">    m:magenta</span></span><br><span class="line"><span class="string">    y:yellow</span></span><br><span class="line"><span class="string">    k:black</span></span><br><span class="line"><span class="string">    w:white</span></span><br><span class="line"><span class="string">其他颜色表示方法</span></span><br><span class="line"><span class="string">    灰色阴影</span></span><br><span class="line"><span class="string">    html十六进制</span></span><br><span class="line"><span class="string">    RGB元祖</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line">y = np.arange(<span class="number">1</span>,<span class="number">5</span>)</span><br><span class="line">y2 = np.arange(<span class="number">2</span>,<span class="number">4</span>)</span><br><span class="line">y3 = np.arange(<span class="number">3</span>,<span class="number">7</span>)</span><br><span class="line">y4 = np.arange(<span class="number">3</span>,<span class="number">1</span>)</span><br><span class="line"><span class="comment"># plt.plot(y)</span></span><br><span class="line"><span class="comment"># plt.plot(y,color=&#x27;green&#x27;)</span></span><br><span class="line">plt.plot(y+<span class="number">1</span>,color=<span class="string">&#x27;m&#x27;</span>,marker=<span class="string">&#x27;o&#x27;</span>)</span><br><span class="line">plt.plot(y+<span class="number">2</span>,color=<span class="string">&#x27;0.6&#x27;</span>,marker=<span class="string">&#x27;^&#x27;</span>)</span><br><span class="line">plt.plot(y+<span class="number">3</span>,color=<span class="string">&#x27;#ff00ff&#x27;</span>,marker=<span class="string">&#x27;D&#x27;</span>)</span><br><span class="line">plt.plot(y+<span class="number">4</span>,color=(<span class="number">0.1</span>,<span class="number">0.2</span>,<span class="number">0.3</span>),marker=<span class="string">&#x27;p&#x27;</span>)</span><br><span class="line"></span><br><span class="line">plt.show()</span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">默认颜色是蓝色</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="第二部分"><a href="#第二部分" class="headerlink" title="第二部分"></a>第二部分</h2><h3 id="chapter10-面向对象-VS-MATLAB-style"><a href="#chapter10-面向对象-VS-MATLAB-style" class="headerlink" title="chapter10 面向对象 VS MATLAB style"></a>chapter10 面向对象 VS MATLAB style</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/15 11:43&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">面向对象 VS MATLAB style </span></span><br><span class="line"><span class="string">三种方式优劣</span></span><br><span class="line"><span class="string">- pyplot:简单易用,交互使用时方便,可以根据命令实时作图.但是底层的定制能力不足.</span></span><br><span class="line"><span class="string">- pylab: 完全封装,环境最接近Matlab.不推荐使用</span></span><br><span class="line"><span class="string">- 面向对象: (Object-Oriented)的方式:接近Matplotlib基础和底层的方式.难度稍大.但是定制能力强,而且是matplotlib的精髓</span></span><br><span class="line"><span class="string">总结: 实战中推荐,根据需求,综合使用pyplot和OO的方式,显示导入numpy</span></span><br><span class="line"><span class="string">常用模块导入代码:</span></span><br><span class="line"><span class="string">import matplotlib.pyplot as plt</span></span><br><span class="line"><span class="string">import numpy as np</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># from pylab import *</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># x = arange(0,10,1)</span></span><br><span class="line"><span class="comment"># y = randn(len(x))</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># plot(x,y)</span></span><br><span class="line"><span class="comment"># title(&#x27;pylib&#x27;)</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># show()</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># # 这种方式写起来很像matlab,但是我们不推荐使用</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 第二种方式(我们之前的方式)</span></span><br><span class="line"><span class="comment"># import matplotlib.pyplot as plt</span></span><br><span class="line"><span class="comment"># import numpy as np</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># x = np.arange(0,10,1)</span></span><br><span class="line"><span class="comment"># y = np.random.randn(len(x))</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># plt.plot(x,y)</span></span><br><span class="line"><span class="comment"># plt.title(&#x27;pyplot&#x27;)</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第三种方式(面向对象方式)</span></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">解决Python使用matplotlib绘图时出现的中文乱码问题</span></span><br><span class="line"><span class="string">最近使用学习Python中使用matplotlib绘图时发现控制台报如下问题，可知是中文字体问题</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line">plt.rcParams[<span class="string">&#x27;font.sans-serif&#x27;</span>]=[<span class="string">&#x27;SimHei&#x27;</span>] <span class="comment">#用来正常显示中文标签</span></span><br><span class="line">plt.rcParams[<span class="string">&#x27;axes.unicode_minus&#x27;</span>]=<span class="literal">False</span> <span class="comment">#用来正常显示负号</span></span><br><span class="line"></span><br><span class="line">x = np.arange(<span class="number">0</span>,<span class="number">10</span>,<span class="number">1</span>)</span><br><span class="line">y = np.random.randn(<span class="built_in">len</span>(x))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">fig = plt.figure()</span><br><span class="line">ax = fig.add_subplot(<span class="number">111</span>)</span><br><span class="line"></span><br><span class="line">l = plt.plot(x,y)</span><br><span class="line">t = ax.set_title(<span class="string">&quot;面向对象方式!~!!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">plt.show()</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="chapter11-matplotlib面向对象简介"><a href="#chapter11-matplotlib面向对象简介" class="headerlink" title="chapter11 matplotlib面向对象简介"></a>chapter11 matplotlib面向对象简介</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/15 12:04&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">matplotlib面向对象简介</span></span><br><span class="line"><span class="string">    FigureCanvas    画布</span></span><br><span class="line"><span class="string">    Figure          图</span></span><br><span class="line"><span class="string">    Axes            坐标轴</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line">x = np.arange(<span class="number">1</span>,<span class="number">100</span>)</span><br><span class="line"></span><br><span class="line">fig = plt.figure()</span><br><span class="line"></span><br><span class="line">ax1 = fig.add_subplot(<span class="number">221</span>)</span><br><span class="line">ax1.plot(x,np.log(x))</span><br><span class="line">ax1 = fig.add_subplot(<span class="number">222</span>)</span><br><span class="line">ax1.plot(x,x*x)</span><br><span class="line">ax1 = fig.add_subplot(<span class="number">223</span>)</span><br><span class="line">ax1.plot(-x,<span class="number">2</span>*x)</span><br><span class="line">ax1 = fig.add_subplot(<span class="number">224</span>)</span><br><span class="line">ax1.plot(-x,x**<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><h3 id="chapter12-figure-多图"><a href="#chapter12-figure-多图" class="headerlink" title="chapter12 figure 多图"></a>chapter12 figure 多图</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/15 22:00&#x27;</span></span><br><span class="line"><span class="string">本节我们讨论figure 多图</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"></span><br><span class="line">fig1 =  plt.figure()</span><br><span class="line"></span><br><span class="line">ax1 = fig1.add_subplot(<span class="number">111</span>)</span><br><span class="line"></span><br><span class="line">ax1.plot([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>],[<span class="number">3</span>,<span class="number">2</span>,<span class="number">1</span>])</span><br><span class="line"></span><br><span class="line">fig2 =  plt.figure()</span><br><span class="line"></span><br><span class="line">ax2 = fig2.add_subplot(<span class="number">111</span>)</span><br><span class="line"></span><br><span class="line">ax2.plot([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>],[<span class="number">3</span>,<span class="number">2</span>,<span class="number">1</span>])</span><br><span class="line"></span><br><span class="line">plt.show()</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="chapter13-网格"><a href="#chapter13-网格" class="headerlink" title="chapter13 网格"></a>chapter13 网格</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/15 22:05&#x27;</span></span><br><span class="line"><span class="string">这回我们画网格</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如何画网格呢?其实就是一句话</span></span><br><span class="line"><span class="comment"># plt.grid(True)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 定制化网格</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 命令行的方式</span></span><br><span class="line"><span class="comment"># import matplotlib.pyplot as plt</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># fig1 =  plt.figure()</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># ax1 = fig1.add_subplot(111)</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># ax1.plot([1,2,3],[3,2,1])</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># fig2 =  plt.figure()</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># ax2 = fig2.add_subplot(111)</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># ax2.plot([1,2,3],[3,2,1])</span></span><br><span class="line"><span class="comment"># plt.grid(True)</span></span><br><span class="line"><span class="comment"># plt.grid(color=&#x27;g&#x27;)</span></span><br><span class="line"><span class="comment"># plt.grid(linewidth=&#x27;2&#x27;)</span></span><br><span class="line"><span class="comment"># # plt.grid(linestyle=&#x27;--&#x27;)</span></span><br><span class="line"><span class="comment"># plt.grid(linestyle=&#x27;-.&#x27;)</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 面向对象的方式绘制网格</span></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成一个图形对象</span></span><br><span class="line">fig = plt.figure()</span><br><span class="line"></span><br><span class="line">x = np.arange(<span class="number">0</span>,<span class="number">10</span>,<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">ax = fig.add_subplot(<span class="number">111</span>)</span><br><span class="line"></span><br><span class="line">plt.plot(x,x**<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">ax.grid(color = <span class="string">&#x27;g&#x27;</span>)</span><br><span class="line"></span><br><span class="line">plt.show()</span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">面向对象是没有交互的效果的</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="chapter14-图例-legend"><a href="#chapter14-图例-legend" class="headerlink" title="chapter14 图例 legend"></a>chapter14 图例 legend</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/15 22:15&#x27;</span></span><br><span class="line"><span class="string">这节我们学习图例 legend</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 同样的是有两种方式,一种是plt的方式,一种是面向对象的方式</span></span><br><span class="line"><span class="comment"># # 第一种方式</span></span><br><span class="line"><span class="comment"># import matplotlib.pyplot as plt</span></span><br><span class="line"><span class="comment"># import numpy as np</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># x = np.arange(1,11,1)</span></span><br><span class="line"><span class="comment"># plt.plot(x,x**2,label=&#x27;Normal&#x27;)</span></span><br><span class="line"><span class="comment"># plt.plot(x,x*2,label=&#x27;Fast&#x27;)</span></span><br><span class="line"><span class="comment"># plt.plot(x,1.5**x,label=&#x27;Faster&#x27;)</span></span><br><span class="line"><span class="comment"># plt.legend()</span></span><br><span class="line"><span class="comment"># # 加上这个就有图例了,能够将上面的label中的内容作为图例的解释上去</span></span><br><span class="line"><span class="comment"># &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># 图例还有一些参数</span></span><br><span class="line"><span class="comment"># 比如位置参数,图例搁哪噶达显示</span></span><br><span class="line"><span class="comment"># &#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 第一点一种方式</span></span><br><span class="line"><span class="comment"># import matplotlib.pyplot as plt</span></span><br><span class="line"><span class="comment"># import numpy as np</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># x = np.arange(1,11,1)</span></span><br><span class="line"><span class="comment"># plt.plot(x,x**2)</span></span><br><span class="line"><span class="comment"># plt.plot(x,x*2)</span></span><br><span class="line"><span class="comment"># plt.plot(x,1.5**x)</span></span><br><span class="line"><span class="comment"># plt.legend([&#x27;Normal&#x27;,&#x27;fast&#x27;,&#x27;slower&#x27;])</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># plt.show()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第二种面向对象的方式</span></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line">x = np.arange(<span class="number">1</span>,<span class="number">11</span>,<span class="number">1</span>)</span><br><span class="line">fig = plt.figure()</span><br><span class="line">ax = fig.add_subplot(<span class="number">111</span>)</span><br><span class="line"></span><br><span class="line">l, = plt.plot(x,x*x)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 1------------------------------------------------</span></span><br><span class="line"><span class="comment"># ax.legend([&#x27;ax legnsd&#x27;])</span></span><br><span class="line"><span class="comment"># 2------------------------------------------------</span></span><br><span class="line">l.set_label(<span class="string">&#x27;label via method&#x27;</span>)</span><br><span class="line">ax.legend()</span><br><span class="line"><span class="comment"># ------------------------------------------------</span></span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><h3 id="chapter15-坐标轴的范围"><a href="#chapter15-坐标轴的范围" class="headerlink" title="chapter15 坐标轴的范围"></a>chapter15 坐标轴的范围</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/15 22:32&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 今天我们来调整一下坐标轴的范围</span></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line">x = np.arange(-<span class="number">10</span>,<span class="number">11</span>,<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">plt.plot(x,x*x)</span><br><span class="line"><span class="comment"># plt.axis([-5,10,0,100])</span></span><br><span class="line"><span class="comment"># axis 调整两个</span></span><br><span class="line"><span class="comment"># plt.axis(xmin=-2)</span></span><br><span class="line"><span class="comment"># xlim 调整单独的一个</span></span><br><span class="line">plt.xlim([-<span class="number">6</span>,<span class="number">9</span>])</span><br><span class="line">plt.ylim([-<span class="number">5</span>,<span class="number">79</span>])</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><h3 id="chapter16-坐标轴的刻度"><a href="#chapter16-坐标轴的刻度" class="headerlink" title="chapter16 坐标轴的刻度"></a>chapter16 坐标轴的刻度</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">#!/usr/bin/env python</span></span><br><span class="line"><span class="string"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="string"># Created by victor</span></span><br><span class="line"><span class="string"># Created Time: &#x27;2020/2/15 22:39&#x27;</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 调整坐标轴的刻度</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line">x = np.arange(-<span class="number">10</span>,<span class="number">11</span>,<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">plt.plot(x,x*x)</span><br><span class="line">ax = plt.gca()  <span class="comment"># 获取当前图形的坐标轴</span></span><br><span class="line"><span class="comment"># ax.locator_params(nbins = 25)</span></span><br><span class="line">ax.locator_params(<span class="string">&#x27;x&#x27;</span>,nbins = <span class="number">25</span>)</span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">这个面向对象是没有交互功能的</span></span><br><span class="line"><span class="string">所以不能再运行后再python控制台进行设定</span></span><br><span class="line"><span class="string">如果想要设置就需要使用plt自带的函数来进行设定</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line">plt.show()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
            <tag> data_analysis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python生成requirements.txt的两种方法</title>
      <link href="python/collection/python-requirements/"/>
      <url>python/collection/python-requirements/</url>
      
        <content type="html"><![CDATA[<div id="content">    <p>python项目如何在另一个环境上重新构建项目所需要的运行环境依赖包？</p>    <p>使用的时候边记载是个很麻烦的事情，总会出现遗漏的包的问题，这个时候手动安装也很麻烦，不能确定代码报错的需要安装的包是什么版本。这些问题，requirements.txt都可以解决！</p>    <p>生成requirements.txt，有两种方式：</p>    <p>第一种 适用于 <strong>单虚拟环境的情况：</strong> ：</p>    <div class="jb51code">        <div>            <div id="highlighter_464138" class="syntaxhighlighter  py">                <div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div>                <table border="0" cellpadding="0" cellspacing="0">                    <tbody>                    <tr>                        <td class="gutter">                            <div class="line number1 index0 alt2">1</div>                        </td>                        <td class="code">                            <div class="container">                                <div class="line number1 index0 alt2"><code class="py plain">pip freeze &gt;                                    requirements.txt</code></div>                            </div>                        </td>                    </tr>                    </tbody>                </table>            </div>        </div>    </div>    <p>为什么只适用于单虚拟环境？因为这种方式，会将环境中的依赖包全都加入，如果使用的全局环境，则下载的所有包都会在里面，不管是不时当前项目依赖的，如下图</p>    <p style="text-align: center"><img alt="" src= "/img/loading.gif" data-lazy-src="//files.jb51.net/file_images/article/201909/2019091810141718.png">    </p>    <p>当然这种情况并不是我们想要的，当我们使用的是全局环境时，可以使用第二种方法。</p>    <p>第二种 <strong>(推荐)</strong> 使用 <code>pipreqs</code> ，github地址为： https://github.com/bndr/pipreqs</p>    <div class="jb51code">        <div>            <div id="highlighter_117559" class="syntaxhighlighter  py">                <div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div>                <table border="0" cellpadding="0" cellspacing="0">                    <tbody>                    <tr>                        <td class="gutter">                            <div class="line number1 index0 alt2">1</div>                            <div class="line number2 index1 alt1">2</div>                            <div class="line number3 index2 alt2">3</div>                            <div class="line number4 index3 alt1">4</div>                        </td>                        <td class="code">                            <div class="container">                                <div class="line number1 index0 alt2"><code class="py comments"># 安装</code></div>                                <div class="line number2 index1 alt1"><code class="py plain">pip install pipreqs</code>                                </div>                                <div class="line number3 index2 alt2"><code class="py comments"># 在当前目录生成</code></div>                                <div class="line number4 index3 alt1"><code class="py plain">pipreqs . </code><code                                        class="py keyword">-</code><code class="py keyword">-</code><code                                        class="py plain">encoding</code><code class="py keyword">=</code><code                                        class="py plain">utf8 </code><code class="py keyword">-</code><code                                        class="py keyword">-</code><code class="py plain">force</code></div>                            </div>                        </td>                    </tr>                    </tbody>                </table>            </div>        </div>    </div>    <p>注意 <code>--encoding=utf8</code> 为使用utf8编码，不然可能会报UnicodeDecodeError: 'gbk' codec can't decode byte 0xae in        position 406: illegal multibyte sequence 的错误。</p>    <p><code>--force</code> 强制执行，当 生成目录下的requirements.txt存在时覆盖。</p>    <p>当当当，可以看见我依赖的只有这些啦</p>    <p style="text-align: center"><img alt="" src= "/img/loading.gif" data-lazy-src="//files.jb51.net/file_images/article/201909/2019091810141719.png">    </p>    <p>使用requirements.txt安装依赖的方式：</p>    <div class="jb51code">        <div>            <div id="highlighter_474262" class="syntaxhighlighter  py">                <div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div>                <table border="0" cellpadding="0" cellspacing="0">                    <tbody>                    <tr>                        <td class="gutter">                            <div class="line number1 index0 alt2">1</div>                        </td>                        <td class="code">                            <div class="container">                                <div class="line number1 index0 alt2"><code class="py plain">pip install </code><code                                        class="py keyword">-</code><code class="py plain">r requirements.txt</code>                                </div>                            </div>                        </td>                    </tr>                    </tbody>                </table>            </div>        </div>    </div><pre><code>&lt;p&gt;原文链接：https://segmentfault.com/a/1190000020411620&lt;/p&gt;</code></pre></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python3中深拷贝与浅拷贝</title>
      <link href="python/base/python-copy/"/>
      <url>python/base/python-copy/</url>
      
        <content type="html"><![CDATA[<h1 id="python中关于深拷贝和浅拷贝的详解"><a href="#python中关于深拷贝和浅拷贝的详解" class="headerlink" title="python中关于深拷贝和浅拷贝的详解"></a>python中关于深拷贝和浅拷贝的详解</h1><h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p>在python的语法中,有两种变量的拷贝方式<br>一种是深拷贝,一种是浅拷贝</p><h3 id="我们先说深拷贝"><a href="#我们先说深拷贝" class="headerlink" title="我们先说深拷贝"></a>我们先说深拷贝</h3><h5 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h5><p>这里需要通过导入系统的copy模块中的deepcopy才可以<br>import copy<br>新的对象 = copy.deepcopy(被拷贝对象)</p><h5 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h5><p>深拷贝是将操作对象整体复制出来一份,与其原来拷贝的对象没有联系,拷贝后重新分配一个内存地址<br>对拷贝和的对象进行各种操作,原对象也不收到影响</p><h3 id="再来说浅拷贝"><a href="#再来说浅拷贝" class="headerlink" title="再来说浅拷贝"></a>再来说浅拷贝</h3><h5 id="语法-1"><a href="#语法-1" class="headerlink" title="语法"></a>语法</h5><p>浅拷贝的语法很多<br>新的对象 = 被拷贝对象<br>新的对象 = 被拷贝对象.copy()<br>新的对象 = lis被拷贝对象t0[:]<br>import copy<br>新的对象 = copy.copy(被拷贝对象)</p><h5 id="解释-1"><a href="#解释-1" class="headerlink" title="解释"></a>解释</h5><p>浅拷贝中,虽然对象本身的地址发生了改变,但是对象中包含的数据还是原来的地址,仅仅是传递过来一个引用<br>指向了原来对象中的数据,如果改变其中一个对象中的内容,其另一方也会对应更改<br>(这里需要注意,如果更改的数据类型是不可更改对象,则改变的是其引用,本身没有改变,只是这个位置的数据换成了另一个地址中的)</p><h3 id="下面看一下代码的测试-小编的测试环境是python3-8版本"><a href="#下面看一下代码的测试-小编的测试环境是python3-8版本" class="headerlink" title="下面看一下代码的测试(小编的测试环境是python3.8版本)"></a>下面看一下代码的测试(小编的测试环境是python3.8版本)</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> copy</span><br><span class="line"></span><br><span class="line">list0 = [[<span class="string">&#x27;abc&#x27;</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>]</span><br><span class="line">list1 = list0</span><br><span class="line">list2 = list0.copy()</span><br><span class="line">list3 = list0[:]</span><br><span class="line">list4 = copy.copy(list0)</span><br><span class="line">list5 = copy.deepcopy(list0)</span><br><span class="line">list6 = copy.deepcopy(list0)</span><br><span class="line"></span><br><span class="line">print(<span class="string">&#x27;0&#x27;</span>, list0, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list0), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list0[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;1&#x27;</span>, list1, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list1), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list1[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;2&#x27;</span>, list2, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list2), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list2[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;3&#x27;</span>, list3, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list3), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list3[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;4&#x27;</span>, list4, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list4), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list4[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;5&#x27;</span>, list5, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list5), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list5[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;6&#x27;</span>, list6, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list6), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list6[<span class="number">0</span>]))</span><br><span class="line"></span><br><span class="line">print(<span class="string">&#x27;---------------------------------改变拷贝对象的内容--------------------------------&#x27;</span>)</span><br><span class="line"></span><br><span class="line">list1[<span class="number">0</span>] = <span class="number">1</span></span><br><span class="line">list2[<span class="number">0</span>] = <span class="number">2</span></span><br><span class="line">list3[<span class="number">0</span>] = <span class="number">3</span></span><br><span class="line">list4[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">4</span></span><br><span class="line">list5[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">5</span></span><br><span class="line">list6[<span class="number">0</span>] = <span class="number">6</span></span><br><span class="line"></span><br><span class="line">print(<span class="string">&#x27;0&#x27;</span>, list0, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list0), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list0[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;1&#x27;</span>, list1, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list1), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list1[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;2&#x27;</span>, list2, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list2), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list2[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;3&#x27;</span>, list3, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list3), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list3[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;4&#x27;</span>, list4, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list4), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list4[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;5&#x27;</span>, list5, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list5), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list5[<span class="number">0</span>]))</span><br><span class="line">print(<span class="string">&#x27;6&#x27;</span>, list6, <span class="string">&#x27;拷贝的对象的地址:&#x27;</span>, <span class="built_in">id</span>(list6), <span class="string">&#x27;第一个元素的地址:&#x27;</span>, <span class="built_in">id</span>(list6[<span class="number">0</span>]))</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>结果如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">D:\Python38\python.exe E:/PycharmProjects/python_August/day09/关于列表的拷贝问题.py</span><br><span class="line"><span class="number">0</span> [[<span class="string">&#x27;abc&#x27;</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209540405760</span> 第一个元素的地址: <span class="number">2209541417472</span></span><br><span class="line"><span class="number">1</span> [[<span class="string">&#x27;abc&#x27;</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209540405760</span> 第一个元素的地址: <span class="number">2209541417472</span></span><br><span class="line"><span class="number">2</span> [[<span class="string">&#x27;abc&#x27;</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209540405888</span> 第一个元素的地址: <span class="number">2209541417472</span></span><br><span class="line"><span class="number">3</span> [[<span class="string">&#x27;abc&#x27;</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209541418112</span> 第一个元素的地址: <span class="number">2209541417472</span></span><br><span class="line"><span class="number">4</span> [[<span class="string">&#x27;abc&#x27;</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209541417152</span> 第一个元素的地址: <span class="number">2209541417472</span></span><br><span class="line"><span class="number">5</span> [[<span class="string">&#x27;abc&#x27;</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209541418176</span> 第一个元素的地址: <span class="number">2209541417792</span></span><br><span class="line"><span class="number">6</span> [[<span class="string">&#x27;abc&#x27;</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209541417856</span> 第一个元素的地址: <span class="number">2209541416896</span></span><br><span class="line">---------------------------------改变拷贝对象的内容--------------------------------</span><br><span class="line"><span class="number">0</span> [<span class="number">1</span>, <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209540405760</span> 第一个元素的地址: <span class="number">140708592568128</span></span><br><span class="line"><span class="number">1</span> [<span class="number">1</span>, <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209540405760</span> 第一个元素的地址: <span class="number">140708592568128</span></span><br><span class="line"><span class="number">2</span> [<span class="number">2</span>, <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209540405888</span> 第一个元素的地址: <span class="number">140708592568160</span></span><br><span class="line"><span class="number">3</span> [<span class="number">3</span>, <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209541418112</span> 第一个元素的地址: <span class="number">140708592568192</span></span><br><span class="line"><span class="number">4</span> [[<span class="number">4</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209541417152</span> 第一个元素的地址: <span class="number">2209541417472</span></span><br><span class="line"><span class="number">5</span> [[<span class="number">5</span>], <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209541418176</span> 第一个元素的地址: <span class="number">2209541417792</span></span><br><span class="line"><span class="number">6</span> [<span class="number">6</span>, <span class="string">&#x27;秋叶夏风&#x27;</span>] 拷贝的对象的地址: <span class="number">2209541417856</span> 第一个元素的地址: <span class="number">140708592568288</span></span><br><span class="line"></span><br><span class="line">Process finished <span class="keyword">with</span> exit code <span class="number">0</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> base </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python虚拟环境--virtualenv</title>
      <link href="python/collection/python-venv/"/>
      <url>python/collection/python-venv/</url>
      
        <content type="html"><![CDATA[<div class="post">    <h1 class="postTitle"><pre><code>    &lt;a id=&quot;cb_post_title_url&quot; class=&quot;postTitle2&quot; href=&quot;https://www.cnblogs.com/technologylife/p/6635631.html&quot;&gt;python虚拟环境--virtualenv&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;postBody&quot;&gt;    &lt;div id=&quot;cnblogs_post_body&quot; class=&quot;blogpost-body &quot;&gt;        &lt;p&gt;&lt;span style=&quot;font-size: 14px;&quot;&gt;　　&lt;span style=&quot;font-size: 15px;&quot;&gt;virtualenv&amp;nbsp;是一个创建隔绝的Python环境的工具。virtualenv创建一个包含所有必要的可执行文件的文件夹，用来使用Python工程所需的包。&lt;/span&gt;&lt;/span&gt;        &lt;/p&gt;        &lt;h3&gt;　　安装&lt;/h3&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;&lt;span                    style=&quot;font-family: 黑体; font-size: 14px;&quot;&gt;&lt;strong&gt;pip install virtualenv&lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;        &lt;/div&gt;        &lt;h3&gt;　　基本使用&lt;/h3&gt;        &lt;ol class=&quot;arabic simple&quot;&gt;            &lt;li&gt;为一个工程创建一个虚拟环境：&lt;/li&gt;        &lt;/ol&gt;        &lt;div class=&quot;highlight-console&quot;&gt;            &lt;div class=&quot;highlight&quot;&gt;                &lt;div class=&quot;cnblogs_code&quot;&gt;</code></pre><pre><span style="color: #000000;"><strong><span style="font-size: 14px; font-family: 'Microsoft YaHei';">$ cd my_project_dir$ virtualenv venv　</span></strong>　<strong>#venv为虚拟环境目录名，目录名自定义</strong></span></pre><pre><code>                &lt;/div&gt;            &lt;/div&gt;        &lt;/div&gt;        &lt;p&gt;&lt;code class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;　　virtualenv&amp;nbsp;&lt;span                class=&quot;pre&quot;&gt;venv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&amp;nbsp;将会在当前的目录中创建一个文件夹，包含了Python可执行文件，以及&amp;nbsp;&lt;code                class=&quot;docutils literal&quot;&gt;pip&lt;/code&gt;&amp;nbsp;库的一份拷贝，这样就能安装其他包了。虚拟环境的名字（此例中是&amp;nbsp;&lt;code                class=&quot;docutils literal&quot;&gt;venv&lt;/code&gt;&amp;nbsp;）可以是任意的；若省略名字将会把文件均放在当前目录。&lt;/p&gt;        &lt;p&gt;　　在任何你运行命令的目录中，这会创建Python的拷贝，并将之放在叫做&amp;nbsp;&lt;code class=&quot;file docutils literal&quot;&gt;venv&lt;/code&gt;&amp;nbsp;的文件中。&lt;/p&gt;        &lt;p&gt;　　你可以选择使用一个Python解释器：&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;&lt;span style=&quot;font-size: 14px; font-family: &#39;Microsoft YaHei&#39;;&quot;&gt;&lt;strong&gt;$ virtualenv -p /usr/bin/python2.7 venv&lt;/strong&gt;&lt;/span&gt;　　　　&lt;strong&gt;# -p参数指定Python解释器程序路径&lt;/strong&gt;&lt;/pre&gt;        &lt;/div&gt;        &lt;p&gt;　　这将会使用&amp;nbsp;&lt;code class=&quot;file docutils literal&quot;&gt;/usr/bin/python2.7&lt;/code&gt;&amp;nbsp;中的Python解释器。&lt;/p&gt;        &lt;p&gt;&amp;nbsp;&lt;/p&gt;        &lt;ol class=&quot;arabic simple&quot; start=&quot;2&quot;&gt;            &lt;li&gt;要开始使用虚拟环境，其需要被激活：&lt;/li&gt;        &lt;/ol&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;&lt;strong&gt;&lt;span style=&quot;font-size: 14px; font-family: &#39;Microsoft YaHei&#39;;&quot;&gt;$ source venv/bin/activate　　　&lt;/span&gt;&lt;/strong&gt;&lt;/pre&gt;        &lt;/div&gt;        &lt;p&gt;&lt;code class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;&lt;span class=&quot;pre&quot;&gt;从现在起，任何你使用pip安装的包将会放在&amp;nbsp;&lt;span                class=&quot;pre&quot;&gt;venv&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&amp;nbsp;文件夹中，与全局安装的Python隔绝开。&lt;/p&gt;        &lt;p&gt;像平常一样安装包，比如：&lt;/p&gt;        &lt;div class=&quot;highlight-console&quot;&gt;            &lt;div class=&quot;highlight&quot;&gt;</code></pre><pre><span class="gp">$ pip install requests</span></pre><pre><code>            &lt;/div&gt;        &lt;/div&gt;        &lt;ol class=&quot;arabic simple&quot; start=&quot;3&quot;&gt;            &lt;li&gt;如果你在虚拟环境中暂时完成了工作，则可以停用它：&lt;/li&gt;        &lt;/ol&gt;        &lt;div class=&quot;highlight-console&quot;&gt;            &lt;div class=&quot;highlight&quot;&gt;                &lt;div class=&quot;cnblogs_code&quot;&gt;                    &lt;pre&gt;&lt;strong&gt;&lt;span style=&quot;font-size: 15px;&quot;&gt;$ . venv/bin/deactivate&lt;/span&gt;&lt;/strong&gt;&lt;/pre&gt;                &lt;/div&gt;            &lt;/div&gt;        &lt;/div&gt;        &lt;p&gt;这将会回到系统默认的Python解释器，包括已安装的库也会回到默认的。&lt;/p&gt;        &lt;p&gt;要删除一个虚拟环境，只需删除它的文件夹。（执行&amp;nbsp;&lt;code class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;rm&amp;nbsp;&lt;span class=&quot;pre&quot;&gt;-rf&amp;nbsp;&lt;span                class=&quot;pre&quot;&gt;venv&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&amp;nbsp;）。&lt;/p&gt;        &lt;p&gt;这里virtualenv 有些不便，因为virtual的启动、停止脚本都在特定文件夹，可能一段时间后，你可能会有很多个虚拟环境散落在系统各处，你可能忘记它们的名字或者位置。&lt;/p&gt;        &lt;h2&gt;virtualenvwrapper&lt;/h2&gt;        &lt;p&gt;　　鉴于virtualenv不便于对虚拟环境集中管理，所以推荐直接使用virtualenvwrapper。&amp;nbsp;virtualenvwrapper提供了一系列命令使得和虚拟环境工作变得便利。它把你所有的虚拟环境都放在一个地方。&lt;/p&gt;        &lt;p&gt;　　安装virtualenvwrapper(确保virtualenv已安装)&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;pip install virtualenvwrapper&lt;br&gt;pip install virtualenvwrapper-win　　#Windows使用该命令&lt;/pre&gt;        &lt;/div&gt;        &lt;p&gt;　　安装完成后，在~/.bashrc写入以下内容&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;export WORKON_HOME=~/&lt;span&gt;Envs&lt;br&gt;&lt;/span&gt;&lt;span&gt;source &lt;/span&gt;/usr/local/bin/virtualenvwrapper.sh　　&lt;/pre&gt;        &lt;/div&gt;        &lt;p&gt;　　第一行：v&lt;span style=&quot;font-size: 14px;&quot;&gt;irtualenvwrapper存放虚拟环境目录&lt;/span&gt;&lt;/p&gt;        &lt;p&gt;&lt;em style=&quot;font-family: &#39;Courier New&#39;; font-size: 12px; line-height: 1.5;&quot;&gt;&lt;span                style=&quot;font-size: 14px;&quot;&gt;　&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;font-size: 14px;&quot;&gt;　第二行：&lt;/span&gt;virtrualenvwrapper会安装到python的bin目录下，所以该路径是python安装目录下bin/virtualenvwrapper.sh        &lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;source ~/.bashrc　　　　#读入配置文件，立即生效&lt;/pre&gt;        &lt;/div&gt;        &lt;p&gt;　&lt;/p&gt;        &lt;p&gt;　virtualenvwrapper基本使用&lt;/p&gt;        &lt;p&gt;1.创建虚拟环境　&lt;strong&gt;mkvirtualenv&lt;/strong&gt;&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;mkvirtualenv venv　　　&lt;/pre&gt;        &lt;/div&gt;        &lt;p&gt;　　这样会在WORKON_HOME变量指定的目录下新建名为venv的虚拟环境。&lt;/p&gt;        &lt;p&gt;　　若想指定python版本，可通过&quot;--python&quot;指定python解释器&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;mkvirtualenv --python=/usr/local/python3.&lt;span                    style=&quot;color: #800080;&quot;&gt;5.3&lt;/span&gt;/bin/python venv&lt;/pre&gt;        &lt;/div&gt;        &lt;p&gt;2. 基本命令&amp;nbsp;　&lt;/p&gt;        &lt;p&gt;&lt;strong&gt;　　&lt;/strong&gt;查看当前的虚拟环境目录&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;</code></pre><pre>[root@localhost ~<span style="color: #000000;">]# workonpy2py3</span></pre><pre><code>        &lt;/div&gt;        &lt;p&gt;　　切换到虚拟环境&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;</code></pre><pre>[root@localhost ~<span style="color: #000000;">]# workon py3(py3) [root@localhost </span>~]# </pre><pre><code>        &lt;/div&gt;        &lt;p&gt;　　退出虚拟环境&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;</code></pre><pre>(py3) [root@localhost ~<span style="color: #000000;">]# deactivate[root@localhost </span>~]# </pre><pre><code>        &lt;/div&gt;        &lt;p&gt;　　删除虚拟环境&lt;/p&gt;        &lt;div class=&quot;cnblogs_code&quot;&gt;            &lt;pre&gt;rmvirtualenv venv&lt;/pre&gt;        &lt;/div&gt;        &lt;p&gt;&amp;nbsp;&lt;/p&gt;        &lt;p&gt;&amp;nbsp;&lt;/p&gt;        &lt;p&gt;本文参考链接：http://pythonguidecn.readthedocs.io/zh/latest/dev/virtualenvs.html&lt;/p&gt;        &lt;p&gt;&amp;nbsp;&lt;/p&gt;    &lt;/div&gt;&lt;/div&gt;</code></pre></div>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python之MD5加密</title>
      <link href="python/collection/python-md5/"/>
      <url>python/collection/python-md5/</url>
      
        <content type="html"><![CDATA[<article class="baidu_pl">    <!--python安装手册开始-->    <!--python安装手册结束-->    <!--####专栏广告位图文切换开始-->    <!--####专栏广告位图文切换结束-->    <div id="article_content" class="article_content clearfix">        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-833878f763.css">        <div id="content_views" class="markdown_views">            <!-- flowchart 箭头图标 勿删 -->            <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">                <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block"                      style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>            </svg>            <blockquote>                <p><strong>Python 3下MD5加密</strong></p>            </blockquote><pre><code>        &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs vala has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                                   style=&quot;position: unset;&quot;&gt;            &lt;span class=&quot;hljs-preprocessor&quot;&gt;# 由于MD5模块在python3中被移除&lt;/span&gt;            &lt;span class=&quot;hljs-preprocessor&quot;&gt;# 在python3中使用hashlib模块进行md5操作&lt;/span&gt;</code></pre><p>import hashlib</p><p><span class="hljs-preprocessor"># 待加密信息</span><br>str = <span class="hljs-string">‘this is a md5 test.’</span></p><p><span class="hljs-preprocessor"># 创建md5对象</span><br>hl = hashlib.md5()</p><p><span class="hljs-preprocessor"># Tips</span><br><span class="hljs-preprocessor"># 此处必须声明encode</span><br><span class="hljs-preprocessor"># 若写法为hl.update(str)  报错为： Unicode-objects must be encoded before hashing</span><br>hl.update(str.encode(encoding=<span class="hljs-string">‘utf-8’</span>))</p><p>print(<span class="hljs-string">‘MD5加密前为 ：’</span> + str)<br>print(<span class="hljs-string">‘MD5加密后为 ：’</span> + hl.hexdigest())<div class="hljs-button {2}" data-title="复制"></div></code><ul                    class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li                    style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li                    style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li                    style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li                    style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li                    style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li                    style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li                    style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li                    style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li                    style="color: rgb(153, 153, 153);">18</li></ul></pre></p><pre><code>        &lt;blockquote&gt;            &lt;p&gt;&lt;strong&gt;运行结果&lt;/strong&gt;&lt;/p&gt;        &lt;/blockquote&gt;        &lt;p&gt;            &lt;img src=&quot;https://img-blog.csdn.net/20170704143346220?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfODc4Nzk5NTc5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast&quot;                 alt=&quot;这里写图片描述&quot; title=&quot;&quot;&gt;&lt;/p&gt;        &lt;blockquote&gt;            &lt;p&gt;&lt;strong&gt;封装Python3下MD5加密&lt;/strong&gt;&lt;/p&gt;        &lt;/blockquote&gt;        &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs python has-numbering&quot; onclick=&quot;mdcp.copyCode(event)&quot;                                                   style=&quot;position: unset;&quot;&gt;</code></pre><p><span class="hljs-comment"># 生成MD5</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">genearteMD5</span><span        class="hljs-params">(str)</span>:</span><br>    <span class="hljs-comment"># 创建md5对象</span><br>    hl = hashlib.md5()</p><pre><code>&lt;span class=&quot;hljs-comment&quot;&gt;# Tips&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 此处必须声明encode&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 否则报错为：hl.update(str)    Unicode-objects must be encoded before hashing&lt;/span&gt;hl.update(str.encode(encoding=&lt;span class=&quot;hljs-string&quot;&gt;&#39;utf-8&#39;&lt;/span&gt;))print(&lt;span class=&quot;hljs-string&quot;&gt;&#39;MD5加密前为 ：&#39;&lt;/span&gt; + str)print(&lt;span class=&quot;hljs-string&quot;&gt;&#39;MD5加密后为 ：&#39;&lt;/span&gt; + hl.hexdigest())&lt;div class=&quot;hljs-button &#123;2&#125;&quot;                                                                         data-title=&quot;复制&quot;&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul                class=&quot;pre-numbering&quot; style=&quot;&quot;&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;1&lt;/li&gt;&lt;li                style=&quot;color: rgb(153, 153, 153);&quot;&gt;2&lt;/li&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;3&lt;/li&gt;&lt;li                style=&quot;color: rgb(153, 153, 153);&quot;&gt;4&lt;/li&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;5&lt;/li&gt;&lt;li                style=&quot;color: rgb(153, 153, 153);&quot;&gt;6&lt;/li&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;7&lt;/li&gt;&lt;li                style=&quot;color: rgb(153, 153, 153);&quot;&gt;8&lt;/li&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;9&lt;/li&gt;&lt;li                style=&quot;color: rgb(153, 153, 153);&quot;&gt;10&lt;/li&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;11&lt;/li&gt;&lt;li                style=&quot;color: rgb(153, 153, 153);&quot;&gt;12&lt;/li&gt;&lt;li style=&quot;color: rgb(153, 153, 153);&quot;&gt;13&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;        &lt;blockquote&gt;            &lt;p&gt;&lt;strong&gt;Python2版本中带有MD5模块生成MD5 如下&lt;/strong&gt;&lt;/p&gt;        &lt;/blockquote&gt;        &lt;pre class=&quot;prettyprint&quot; name=&quot;code&quot;&gt;&lt;code class=&quot;hljs coffeescript has-numbering&quot;                                                   onclick=&quot;mdcp.copyCode(event)&quot; style=&quot;position: unset;&quot;&gt;&lt;span                class=&quot;hljs-reserved&quot;&gt;import&lt;/span&gt; md5</code></pre><p>src = <span class="hljs-string">‘this is a md5 test.’</span><br>m1 = md5.<span class="hljs-keyword">new</span>()<br>m1.update(src.encode(encoding=<span class="hljs-string">‘utf-8’</span>))<br><span class="hljs-built_in">print</span>(m1.hexdigest())</p><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li                    style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li                    style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li                    style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li                    style="color: rgb(153, 153, 153);">7</li></ul></pre>        </div>        <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-b6c3c6d139.css" rel="stylesheet">        </article>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python 四大主流 Web 编程框架</title>
      <link href="python/collection/python-frame/"/>
      <url>python/collection/python-frame/</url>
      
        <content type="html"><![CDATA[<br>目前Python的网络编程框架已经多达几十个，逐个学习它们显然不现实。但这些框架在系统架构和运行环境中有很多共通之处，本文带领读者学习基于Python网络框架开发的常用知识,及目前的4种主流Python网络框架：Django、Tornado、Flask、Twisted。<p>网络框架及MVC架构<br>所谓网络框架是指这样的一组Python包，它能够使开发者专注于网站应用业务逻辑的开发，而无须处理网络应用底层的协议、线程、进程等方面。这样能大大提高开发者的工作效率，同时提高网络应用程序的质量。</p><p>    在目前Python语言的几十个开发框架中，几乎所有的全栈网络框架都强制或引导开发者使用MVC架构开发Web应用。所谓全栈网络框架，是指除了封装网络和线程操作，还提供HTTP栈、数据库读写管理、HTML模板引擎等一系列功能的网络框架。本文重点讲解的Django、Tornado和Flask是全栈网络框架的典型标杆；而Twisted更专注于网络底层的高性能封装而不提供HTML模板引擎等界面功能，所以不能称之为全栈框架。</p><p>MVC（Model-View-Controller）模式最早由Trygve    Reenskaug在1978年提出，在20世纪80年代是程序语言Smalltalk的一种内部架构。后来MVC被其他语言所借鉴，成为了软件工程中的一种软件架构模式。MVC把Web应用系统分为3个基本部分。</p><p>    模型（Model）：用于封装与应用程序的业务逻辑相关的数据及对数据的处理方法，是Web应用程序中用于处理应用程序的数据逻辑的部分，Model只提供功能性的接口，通过这些接口可以获取Model的所有功能。Model不依赖于View和Controller，它们可以在任何时候调用Model访问数据。有些Model还提供了事件通知机制，为在其上注册过的View或Controller提供实时的数据更新。</p><p>视图（View）：负责数据的显示和呈现，View是对用户的直接输出。MVC中的一个Model通常为多个View提供服务。为了获取Model的实时更新数据，View应该尽早地注册到Model中。</p><p>    控制器（Controller）：负责从用户端收集用户的输入，可以看成提供View的反向功能。当用户的输入导致View发生变化时，这种变化必须是通过Model反映给View的。在MVC架构下，Controller一般不能与View直接通信，这样提高了业务数据的一致性，即以Model作为数据中心。</p><p>这3个基本部分互相分离，使得在改进和升级界面及用户交互流程时，不需要重写业务逻辑及数据访问代码。MVC架构如图1所示。</p><p>MVC架构图</p><p>注意：MVC在除Python外的其他语言中也有广泛应用，例如VC++的MFC、Java的Structs及Spring、C#的.NET开发框架，读者应该有深刻的体会。<br>4种Python网络框架：Django、Tornado、Flask、Twisted</p><p>接下来学习当今主流的4种Python网络框架。</p><p>企业级开发框架——Django<br>Django于2003年诞生于美国堪萨斯（Kansas）州，最初用来制作在线新闻Web站点，于2005年加入了BSD许可证家族，成为开源网络框架。Django根据比利时的爵士音乐家Django    Reinhardt命名，作者这样命名Django意味着Django能优雅地演奏（开发）功能丰富的乐曲（Web应用）。</p><p>    它是当前Python世界里最负盛名且最成熟的网络框架。最初用来制作在线新闻的Web站点，目前已发展为应用最广泛的Python网络框架。Django的各模块之间结合得比较紧密，所以在功能强大的同时又是一个相对封闭的系统，但是其健全的在线文档及开发社区，使开发者在遇到问题时能找到解决方法。</p><p>Django框架的特点<br>相对于Python的其他Web框架，Django的功能是最完整的，Django定义了服务发布、路由映射、模板编程、数据处理的一整套功能。这也意味着Django模块之间紧密耦合，开发者需要学习Django自己定义的这一整套技术。Django的主要特点如下。</p><p>完善的文档：经过10多年的发展和完善，Django有广泛的应用和完善的在线文档，开发者遇到问题时可以搜索在线文档寻求解决方案。<br>集成数据访问组件：Django的Model层自带数据库ORM组件，使开发者无须学习其他数据库访问技术（dbi、SQLAlchemy等）。<br>强大的URL映射技术：Django使用正则表达式管理URL映射，因此给开发者带来了极高的灵活性。<br>后台管理系统自动生成：开发者只需通过简单的几行配置和代码就可以实现完整的后台数据管理Web控制台。<br>错误信息非常完整：在开发调试过程中如果出现运行异常，则Django可以提供非常完整的错误信息帮助开发者定位问题，比如缺少xxx组件的配置引用等，这样可以使开发者马上改正错误。</p><p>Django的组成结构</p><p>Django是遵循MVC架构的Web开发框架，其主要由以下几部分组成。</p><p>管理工具（Management）：一套内置的创建站点、迁移数据、维护静态文件的命令工具。<br>模型（Model）：提供数据访问接口和模块，包括数据字段、元数据、数据关系等的定义及操作。<br>视图（View）：Django的视图层封装了HTTP    Request和Response的一系列操作和数据流，其主要功能包括URL映射机制、绑定模板等。<br>模板（Template）：是一套Django自己的页面渲染模板语言，用若干内置的tags和filters定义页面的生成方式。<br>表单（Form）：通过内置的数据类型和控件生成HTML表单。<br>管理站（Admin）：通过声明需要管理的Model，快速生成后台数据管理网站。</p><p>高并发处理框架——Tornado<br>Tornado是使用Python编写的一个强大的可扩展的Web服务器。它在处理高网络流量时表现得足够强健，却在创建和编写时有着足够的轻量级，并能够被用在大量的应用和工具中。Tornado作为FriendFeed网站的基础框架，于2009年9月10日发布，目前已经获得了很多社区的支持，并且在一系列不同的场合中得到应用。除FriendFeed和Facebook外，还有很多公司在生产上转向Tornado，包括Quora、Turntable.fm、Bit.ly、Hipmunk及MyYearbook等。</p><p>相对于其他Python网络框架，Tornado有如下特点。</p><p>完备的Web框架：与Django、Flask等一样，Tornado也提供了URL路由映射、Request上下文、基于模板的页面渲染技术等开发Web应用的必备工具。<br>是一个高效的网络库，性能与Twisted、Gevent等底层Python框架相媲美：提供了异步I/O支持、超时事件处理。这使得Tornado除了可以作为Web应用服务器框架，还可以用来做爬虫应用、物联网关、游戏服务器等后台应用。<br>提供高效HTTPClient：除了服务器端框架，Tornado还提供了基于异步框架的HTTP客户端。<br>提供高效的内部HTTP服务器：虽然其他Python网络框架（Django、Flask）也提供了内部HTTP服务器，但它们的HTTP服务器由于性能原因只能用于测试环境。而Tornado的HTTP服务器与Tornado异步调用紧密结合，可以直接用于生产环境。<br>完备的WebSocket支持：WebSocket是HTML5的一种新标准，实现了浏览器与服务器之间的双向实时通信。<br>因为Tornado的上述特点，Tornado常被用作大型站点的接口服务框架，而不像Django那样着眼于建立完整的大型网站，所以本章着重讲解Tornado的异步及协程编程、身份认证框架、独特的非WSGI部署方式。</p><p>支持快速建站的框架——Flask<br>Flask是Python    Web框架族里比较年轻的一个，于2010年出现，这使得它吸收了其他框架的优点，并且把自己的主要领域定义在了微小项目上。同时，它是可扩展的，Flask让开发者自己选择用什么数据库插件存储他们的数据。很多功能简单但性能卓越的网站就是基于Flask框架而搭建的，比如<a            href="https://yq.aliyun.com/go/articleRenderRedirect?url=http%3A%2F%2Fhttpbin.org%2F"            target="_blank" data-url="http://httpbin.org/">http://httpbin.org/</a>就是一个功能简单但性能强大的HTTP测试项目。Flask是一个面向简单需求和小型应用的微框架。</p><p>相对于其他Python语言的Web框架而言，Flask的特点可以归结如下。</p><p>内置开发服务器和调试器<br>网络程序调试是在将编制好的网站投入实际运行前，用手工或编译程序等方法进行测试，修正语法错误和逻辑错误的过程。有经验的开发者都知道，这是保证网站系统能够正式应用的必要步骤。<br>Flask    自带的开发服务器使开发者在调试程序时无须再安装其他任何网络服务器，比如Tomcat、JBoss、Apache等。Flask默认处于调试状态，使得运行中的任何错误会同时向两个目标发送信息：一个是Python    Console，即启动Python程序的控制台；另一个是HTTP客户端，即Flask开发服务器将调试信息传递给了客户端。<br>与Python单元测试功能无缝衔接<br>单元测试是对最小软件开发单元的测试，其重点测试程序的内部结构，主要采用白盒测试方法，由开发人员负责。单元测试的主要目标是保证函数在给定的输入状态下，能够得到预想的输出，在不符合要求时能够提醒开发人员进行检查。<br>Flask提供了一个与Python自带的单元测试框架unitest无缝衔接的测试接口，即Flask对象的test_client()函数。通过test_client()函数，测试程序可以模拟进行HTTP访问的客户端来调用Flask路由处理函数，并且获取函数的输出来进行自定义的验证。<br>使用Jinja2模板<br>将HTML页面与后台应用程序联系起来一直是网站程序框架的一个重要目标。Flask通过使用Jinja2模板技术解决了这个问题。Jinja2是一个非常灵活的HTML模板技术，它是从Django模板发展而来的，但是比Django模板使用起来更加自由且更加高效。Jinja2模板使用配制的语义系统，提供灵活的模板继承技术，自动抗击XSS跨站攻击并且易于调试。<br>完全兼容WSGI    1.0标准<br>WSGI（Web Server Gateway    Interface）具有很强的伸缩性且能运行于多线程或多进程环境下，因为Python线程全局锁的存在，使得WSGI的这个特性至关重要。WSGI已经是Python界的一个主要标准，各种大型网路服务器对其都有良好的支持。WSGI位于Web应用程序与Web服务器之间，与WSGI完全兼容使得Flask能够配置到各种大型网络服务器中。<br>基于Unicode编码<br>Flask是完全基于Unicode的。这对制作非纯ASCII字符集的网站来说非常方便。HTTP本身是基于字节的，也就是说任何编码格式都可以在HTTP中传输。但是，HTTP要求在HTTP    Head中显式地声明在本次传输中所应用的编码格式。在默认情况下，Flask会自动添加一个UTF-8编码格式的HTTP Head，使程序员无须担心编码的问题。</p><p>底层自定义协议网络框架——Twisted</p><p>以上讲到的3个Python    Web框架都是围绕着应用层HTTP展开的，而Twisted是一个例外。Twisted是一个用Python语言编写的事件驱动的网络框架，对于追求服务器程序性能的应用，Twisted框架是一个很好的选择。</p><p>    Twisted是一个有着10多年历史的开源事件驱动框架。Twisted支持很多种协议，包括传输层的UDP、TCP、TLS，以及应用层的HTTP、FTP等。对于所有这些协议，Twisted提供了客户端和服务器方面的开发工具。</p><p>Twisted框架的历史悠久，其主要发行版本都以Python 2为基础，最新的版本为基于Python 2.7的Twisted-15.4.0。Twisted社区正在开发基于Python    3的版本，但目前为止尚没有基于Python 3的Twisted稳定发行版。</p><p>Twisted是一个高性能的编程框架。在不同的操作系统平台上，Twisted利用不同的底层技术实现了高效能通信。在Windows中，Twisted的实现基于I/O完成端口（IOCP，Input/Output    Completion    Port）技术，它保证了底层高效地将I/O事件通知给框架及应用程序；在Linux中，Twisted的实现基于epoll技术，epoll是Linux下多路复用I/O接口select/poll的增强版本，它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。<br>在开发方法上，Twisted引导程序员使用异步编程模型。Twisted提供了丰富的Defer、Threading等特性来支持异步编程。<br>原文地址<a            href="https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fwww.cnblogs.com%2Fan-wen%2Fp%2F11330834.html"            target="_blank" data-url="https://www.cnblogs.com/an-wen/p/11330834.html">https://www.cnblogs.com/an-wen/p/11330834.html</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>什么是AOP（面向切面编程）</title>
      <link href="cp/aop/"/>
      <url>cp/aop/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><p>这种在运行时，动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。</p><p>AOP是Spring提供的关键特性之一。AOP即面向切面编程，是OOP编程的有效补充。使用AOP技术，可以将一些系统性相关的编程工作，独立提取出来，独立实现，然后通过切面切入进系统。从而避免了在业务逻辑的代码中混入很多的系统相关的逻辑——比如权限管理，事物管理，日志记录等等。这些系统性的编程工作都可以独立编码实现，然后通过AOP技术切入进系统即可。从而达到了 将不同的关注点分离出来的效果。本文深入剖析Spring的AOP的原理。</p><h3 id="AOP相关的概念"><a href="#AOP相关的概念" class="headerlink" title="AOP相关的概念"></a>AOP相关的概念</h3><p>1） Aspect ：切面，切入系统的一个切面。比如事务管理是一个切面，权限管理也是一个切面；</p><p>2） Join point ：连接点，也就是可以进行横向切入的位置；</p><p>3） Advice ：通知，切面在某个连接点执行的操作(分为: Before advice , After returning advice , After throwing advice , After (finally) advice , Around advice )；</p><p>4） Pointcut ：切点，符合切点表达式的连接点，也就是真正被切入的地方；</p><h3 id="AOP-的实现原理"><a href="#AOP-的实现原理" class="headerlink" title="AOP 的实现原理"></a>AOP 的实现原理</h3><p>AOP分为静态AOP和动态AOP。静态AOP是指AspectJ实现的AOP，他是将切面代码直接编译到Java类文件中。动态AOP是指将切面代码进行动态织入实现的AOP。Spring的AOP为动态AOP，实现的技术为： JDK提供的动态代理技术 和 CGLIB(动态字节码增强技术) 。尽管实现技术不一样，但 都是基于代理模式 ， 都是生成一个代理对象 。</p><p>作者：breaktian</p><p>链接：<a href="https://www.jianshu.com/p/3ea60002f290">https://www.jianshu.com/p/3ea60002f290</a></p><p>来源：简书</p><p>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。</p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> interview </tag>
            
            <tag> Python </tag>
            
            <tag> oop </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python有毒</title>
      <link href="python/collection/python-virus/"/>
      <url>python/collection/python-virus/</url>
      
        <content type="html"><![CDATA[<p><a href="https://blog.csdn.net/tiantian520ttjs/article/details/102818050">Python3.7编写个Python小病毒（U盘和电脑通中）……（纯属基友恶搞）</a></p><p><a href="https://blog.csdn.net/qq_42022255/article/details/80727818">十行代码–用python写一个USB病毒 (知乎 DeepWeaver)</a></p><p><a href="https://blog.csdn.net/weixin_42904058/article/details/90314276">python3病毒系列(1) “灭霸”</a></p><p><a href="https://blog.csdn.net/weixin_42904058/article/details/90578940">python3病毒系列(2)”木马”</a></p><p><a href="https://www.jianshu.com/p/1e20bfc0cd1b">我背着女朋友，用 Python 偷偷抓取了她的行踪</a></p><p><a href="https://mp.weixin.qq.com/s?__biz=MzU1OTI0NjI1NQ==&mid=2247483911&idx=1&sn=cf6bb9c9db15c12566551d4bbc3fdd86&chksm=fc1b7cc7cb6cf5d177fa1f65837611674da5e0dd2095626a81192255ee6952971cba86c77029&scene=21#wechat_redirect">抖音上好看的小姐姐，Python给你都下载了</a></p><p><a href="https://www.jianshu.com/p/88cfd24750fe">python爬虫：做一个界面爬虫小软件</a></p><p><a href="https://www.jianshu.com/p/84c0a1e93ea6">带你了解Python炫酷的颜色输出与进度条打印</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>正则表达式、xpath和Beautifulsoup的分析和总结</title>
      <link href="python/spider/XPath/xpath-re-bs4/"/>
      <url>python/spider/XPath/xpath-re-bs4/</url>
      
        <content type="html"><![CDATA[<h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p>1.正则表达式是进行内容匹配，将符合要求的内容全部获取；xpath()能将字符串转化为标签，它会检测字符串内容是否为标签，但是不能检<br>测出内容是否为真的标签；Beautifulsoup是Python的一个第三方库，它的作用和 xpath 作用一样，都是用来解析html数据的相比之下，<br>xpath的速度会快一点，因为xpath底层是用c来实现的</p><p>2.三者语法不同，正则表达式使用元字符，将所有获得内容与匹配条件进行匹配，而xpath和bs4将获取的解析后的源码进行按条件筛选，筛选<br>出想要的标签即根据标签属性来找到指定的标签，之后对标签进行对应内容获取。</p><h3 id="Beautifulsoup4"><a href="#Beautifulsoup4" class="headerlink" title="Beautifulsoup4"></a>Beautifulsoup4</h3><p>bs4是一种对性能的要求,时间的限制相对较弱的一种爬取方式.</p><p>bs4爬取数据</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 四种种安装方式</span></span><br><span class="line">pip install beautifulsoup4</span><br><span class="line">easy_install beautifulsoup4</span><br><span class="line"><span class="comment"># 下载tar.gz包 pip setup.py install</span></span><br><span class="line"><span class="comment"># 拷贝别人的bs4文件夹,知己复制到site-pakages/目录下即可</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 从程序中引入bs4</span></span><br><span class="line"><span class="keyword">from</span> bs4 <span class="keyword">import</span> BeautifulSoup</span><br><span class="line"></span><br><span class="line"><span class="comment"># 从网页文件中直接加载</span></span><br><span class="line">soup = BeautifulSoup(<span class="built_in">open</span>(<span class="string">&quot;index.html&quot;</span>), <span class="string">&quot;lxml&quot;</span>)</span><br><span class="line"></span><br><span class="line">print(soup)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="作为爬虫工具对比"><a href="#作为爬虫工具对比" class="headerlink" title="作为爬虫工具对比"></a>作为爬虫工具对比</h3><table><thead><tr><th></th><th>re</th><th>xpath</th><th>bs4</th></tr></thead><tbody><tr><td>安装</td><td>内置</td><td>第三方</td><td>第三方</td></tr><tr><td>语法</td><td>正则</td><td>路径匹配</td><td>面向对象</td></tr><tr><td>使用</td><td>困难</td><td>较困难</td><td>简单</td></tr><tr><td>性能</td><td>最高</td><td>适中</td><td>最低</td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> summer </tag>
            
            <tag> Python </tag>
            
            <tag> regex </tag>
            
            <tag> spider </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python中的单例模式</title>
      <link href="python/base/python-single-mode/"/>
      <url>python/base/python-single-mode/</url>
      
        <content type="html"><![CDATA[<h3 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h3><p>单例模式（Singleton Pattern）是一种常用的软件设计模式，该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中，某个类只能出现一个实例时（如软件配置类，无论在软件的什么地方实例化，永远都是那一个对象），单例模式就能派上用场。比如，Python 日志模块中的日志对象，或者异步通讯框架 twisted 里面的反应堆(reactor)，都是典型的单例模式——尽管它们不一定是下面这种方法实现的。</p><h3 id="python可以使用装饰器的方法使用单例模式："><a href="#python可以使用装饰器的方法使用单例模式：" class="headerlink" title="python可以使用装饰器的方法使用单例模式："></a>python可以使用装饰器的方法使用单例模式：</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">Singleton</span>(<span class="params">cls</span>):</span></span><br><span class="line">    _instance = &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_singleton</span>(<span class="params">*args, **kargs</span>):</span></span><br><span class="line">        <span class="keyword">if</span> cls <span class="keyword">not</span> <span class="keyword">in</span> _instance:</span><br><span class="line">            _instance[cls] = cls(*args, **kargs)</span><br><span class="line">        <span class="keyword">return</span> _instance[cls]</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> _singleton</span><br><span class="line"></span><br><span class="line"><span class="meta">@Singleton</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Config</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">cfg1 = Config()</span><br><span class="line">cfg2 = Config()</span><br><span class="line"></span><br><span class="line">print(cfg1 <span class="keyword">is</span> cfg2)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="结果如下"><a href="#结果如下" class="headerlink" title="结果如下"></a>结果如下</h3><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">D:\<span class="title">Python37</span>\<span class="title">python.exe</span> <span class="title">D</span>:/<span class="title">PycharmProjects</span>/<span class="title">QT_pro</span>/<span class="title">re_demo.py</span></span></span><br><span class="line"><span class="function"><span class="title">True</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">Process</span> <span class="title">finished</span> <span class="title">with</span> <span class="title">exit</span> <span class="title">code</span> 0</span></span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>兄弟会各种技术博文汇总</title>
      <link href="comic/blog-sum/"/>
      <url>comic/blog-sum/</url>
      
        <content type="html"><![CDATA[<p>JS学到位了么:<br><a href="https://tongzebin.github.io/2019/09/04/js%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/">JS的正则表达式</a></p><p>妹子图的GUI:<br><a href="https://raoweijiapng.github.io/python/python%E9%AB%98%E7%BA%A7(5)/">python中tkinter</a></p><p>你危险了:<br><a href="http://mybestow.com/wifi%E6%B8%97%E9%80%8F/">kali WiFi渗透</a></p><p>早餐吃什么:<br><a href="https://llzanz.github.io/2019/10/28/%E8%BF%99%E4%B8%AA%E4%BB%A3%E7%A0%81%E6%98%AF%E7%94%A8%E6%9D%A5%E7%83%AD%E7%89%9B%E5%A5%B6%E7%9A%84/">热一袋牛奶</a></p><p>高级的IDE:<br><a href="https://1978413822.github.io/2019/10/29/2019-10-29-idea%E4%B8%AD%E5%8A%A0%E5%BA%8F%E5%88%97%E5%8C%96/">IDEA加序列化</a></p><p>高效的coding:<br><a href="https://victorfengming.gitee.io/git/git-idea/">智能的想法</a></p><p>理解好了么:<br><a href="https://qijian160.github.io/posts/2019-10-23-integer-ultrices-elit-sit-amet">抽象的东西</a></p><p>开源的系统:<br><a href="https://wxy20170906.github.io/2019/11/18/1%E5%85%84%E5%BC%9F%E4%BC%9A%E7%AC%AC%E4%B8%80%E5%A4%A9/">linux系统的安装</a></p><p>瑕疵QAQ:<br><a href="https://jiesangqaq.github.io/2019/10/22/2019-10-22-Exception/">java中的异常机制</a></p><p>Ubuntu里面:<br><a href="https://nineberg.github.io/blog/note3">显示器旋转</a></p><p>这个不是插件:<br><a href="https://zhengyupengzz.github.io/2019/09/03/2019-09-03-03jishu/">lamp环境搭建</a></p><p>遇到问题怎么办:<br><a href="https://caoyang7.github.io/2019/08/15/a%E5%8A%A0%E6%B2%B9/">加油加油加油</a></p><p>window系统:<br><a href="https://ttk1907.gitee.io/2019/10/17/xiongdihui-problem/">记事本还整不明白了</a></p><p>曾几何时:<br><a href="https://xjx19970831.github.io/abc-Sample-Page">祖国您历尽磨难</a></p><p>刚用idea时:<br><a href="https://yangxin19970404.github.io/2019/10/14/2019-10-14-tomcat%E4%B9%B1%E7%A0%81/">还弄不明白一个猫了</a></p><p>简单易学:<br><a href="https://gaohaibin3000.github.io/blog/2019/10/23/markdown%E7%BB%83%E4%B9%A0/#more">富文本格式</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> entertainment </tag>
            
            <tag> summer </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python pip 安装与使用</title>
      <link href="python/install/python-install-pip/"/>
      <url>python/install/python-install-pip/</url>
      
        <content type="html"><![CDATA[<h3 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h3><div class="article-intro">                    <p>pip 是 Python 包管理工具，该工具提供了对Python 包的查找、下载、安装、卸载的功能。</p><p>目前如果你在 <a target="_blank" href="https://www.python.org">python.org</a> 下载最新版本的安装包，则是已经自带了该工具。</p><p>Python 2.7.9 +  或 Python 3.4+  以上版本都自带 pip 工具。</p><p>pip 官网：<a href="https://pypi.org/project/pip/" target="_blank">https://pypi.org/project/pip/</a></p><p>你可以通过以下命令来判断是否已安装：</p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip </span><span class="pun">--</span><span class="pln">version</span></pre><p>如果你还未安装，则可以使用以下方法来安装：</p><pre class="prettyprint prettyprinted" style=""><span class="pln">$ curl https</span><span class="pun">:</span><span class="com">//bootstrap.pypa.io/get-pip.py -o get-pip.py   # 下载安装脚本</span><span class="pln">$ sudo python </span><span class="kwd">get</span><span class="pun">-</span><span class="pln">pip</span><span class="pun">.</span><span class="pln">py    </span><span class="com"># 运行安装脚本</span></pre><blockquote><p><strong>注意：</strong>用哪个版本的 Python 运行安装脚本，pip 就被关联到哪个版本，如果是 Python3 则执行以下命令：</p><pre class="prettyprint prettyprinted" style=""><span class="pln">$ sudo python3 </span><span class="kwd">get</span><span class="pun">-</span><span class="pln">pip</span><span class="pun">.</span><span class="pln">py    </span><span class="com"># 运行安装脚本。</span></pre><p>一般情况 pip 对应的是 Python 2.7，pip3 对应的是 Python 3.x。</p></blockquote><p>部分 Linux 发行版可直接用包管理器安装 pip，如 Debian 和 Ubuntu：</p><pre class="prettyprint prettyprinted" style=""><span class="pln">sudo apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> install python</span><span class="pun">-</span><span class="pln">pip</span></pre><h3>pip 最常用命令</h3><p><strong>显示版本和路径</strong></p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip </span><span class="pun">--</span><span class="pln">version</span></pre>  <p><strong>获取帮助</strong></p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip </span><span class="pun">--</span><span class="pln">help</span></pre><p><strong>升级 pip</strong></p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip install </span><span class="pun">-</span><span class="pln">U pip</span></pre><blockquote><p>如果这个升级命令出现问题 ，可以使用以下命令：</p><pre class="prettyprint prettyprinted" style=""><span class="pln">sudo easy_install </span><span class="pun">--</span><span class="pln">upgrade pip</span></pre> </blockquote><p><strong>安装包</strong> </p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip install </span><span class="typ">SomePackage</span><span class="pln">              </span><span class="com"># 最新版本</span><span class="pln">pip install </span><span class="typ">SomePackage</span><span class="pun">==</span><span class="lit">1.0</span><span class="pun">.</span><span class="lit">4</span><span class="pln">       </span><span class="com"># 指定版本</span><span class="pln">pip install </span><span class="str">'SomePackage&gt;=1.0.4'</span><span class="pln">     </span><span class="com"># 最小版本</span></pre><p>比如我要安装 Django。用以下的一条命令就可以，方便快捷。</p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip install </span><span class="typ">Django</span><span class="pun">==</span><span class="lit">1.7</span></pre><p><strong>升级包</strong> </p> <pre class="prettyprint prettyprinted" style=""><span class="pln">pip install </span><span class="pun">--</span><span class="pln">upgrade </span><span class="typ">SomePackage</span></pre><p>升级指定的包，通过使用==, &gt;=, &lt;=, &gt;, &lt; 来指定一个版本号。</p><p><strong>卸载包</strong> </p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip uninstall </span><span class="typ">SomePackage</span></pre><p><strong>搜索包</strong></p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip search </span><span class="typ">SomePackage</span></pre><p><strong>显示安装包信息</strong></p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip show </span></pre> <p><strong>查看指定包的详细信息</strong></p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip show </span><span class="pun">-</span><span class="pln">f </span><span class="typ">SomePackage</span></pre><p><strong>列出已安装的包</strong></p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip list</span></pre><p><strong>查看可升级的包</strong></p><pre class="prettyprint prettyprinted" style=""><span class="pln">pip list </span><span class="pun">-</span><span class="pln">o</span></pre><h3>注意事项</h3><p>如果 Python2 和 Python3 同时有 pip，则使用方法如下：</p> <p>Python2：</p><pre class="prettyprint prettyprinted" style=""><span class="pln">python2 </span><span class="pun">-</span><span class="pln">m pip install XXX</span></pre><p>Python3:</p><pre class="prettyprint prettyprinted" style=""><span class="pln">python3 </span><span class="pun">-</span><span class="pln">m pip install XXX</span></pre><pre><code>            &lt;/div&gt;</code></pre>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> basis </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python爬取有道詞典</title>
      <link href="python/spider/python-youdao-spider/"/>
      <url>python/spider/python-youdao-spider/</url>
      
        <content type="html"><![CDATA[<h1 id="python爬虫爬取有道翻译教程"><a href="#python爬虫爬取有道翻译教程" class="headerlink" title="python爬虫爬取有道翻译教程"></a>python爬虫爬取有道翻译教程</h1><h2 id="编写环境"><a href="#编写环境" class="headerlink" title="编写环境"></a>编写环境</h2><p><strong>为了宝宝们能够正确读懂本教程,在正式开始前,宝宝们需要搭建的环境如下:</strong></p><ol><li>连接互联网的win10电脑,(win7也可以)</li><li>Google浏览器(版本无要求)</li><li>Python(版本3就可以了),如果没有安装的小伙伴可以参考<a href="https://blog.csdn.net/qq_40223983/article/details/95655470">python安装以及版本检测</a></li><li>requests库(版本没啥要求),没有安装的小伙伴可以参考<a href="https://blog.csdn.net/IT__LS/article/details/77801743">python request库安装</a></li></ol><h2 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h2><p>我们本次要爬取的网页是:<a href="http://fanyi.youdao.com/">有道翻译</a><br><img src= "/img/loading.gif" data-lazy-src="20190717151250306.png" alt="在这里插入图片描述"><br>这时,按下F12键,调出Google浏览器的开发者工具<br><img src= "/img/loading.gif" data-lazy-src="20190717151618520.png" alt="在这里插入图片描述"><br>现在里面没有内容,别慌,点击NetWork选项卡后,再次点击翻译按钮<br><img src= "/img/loading.gif" data-lazy-src="201907171516579.png" alt="在这里插入图片描述"><br>这时,宝宝们会发现下面多了几条网络请求,我们点击第一个请求<br><img src= "/img/loading.gif" data-lazy-src="20190717152014646.png" alt="在这里插入图片描述"><br>在右边有三个点的按钮,可以切换开发者工具的显示状态,我们点击第一个,让它单独分出一页显示出来,以便于观察<br><img src= "/img/loading.gif" data-lazy-src="20190717152217512.png" alt="在这里插入图片描述"><br>在Headers选项卡中,可以查看这次请求的URL、headers参数<br><img src= "/img/loading.gif" data-lazy-src="2019071715235350.png" alt="在这里插入图片描述"><br>往下面翻,还有data的参数值<br><img src= "/img/loading.gif" data-lazy-src="20190717152420267.png" alt="在这里插入图片描述"><br>我们点击Response来查看这次请求的响应,也就是服务器给我们返回的结果,经过和网页中翻译内容的比较,可以确定,这个数据就是我们需要爬取的内容.<br><img src= "/img/loading.gif" data-lazy-src="20190717152633170.png" alt="在这里插入图片描述"><br>经过我们的多次改变翻译内容,比较请求信息,我们可以发现:</p><p>在data中有三个数据是加密的变量,其中i为我们输入要翻译的字符串,而salt、sign和ts是加密的变值.所以我们猜测这个值是由JavaScript生成的,这里我们可以在页面中右键-&gt;查看网页源代码<br>通过Ctrl+F搜索js,找到js文件<br><img src= "/img/loading.gif" data-lazy-src="20190717153513681.png" alt="在这里插入图片描述"><br>通过向下继续搜索,我们发现了三个以js结尾的文件<br><img src= "/img/loading.gif" data-lazy-src="20190717153733970.png" alt="在这里插入图片描述"><br>依次点击进入后进行搜索,最终确为<br><a href="http://shared.ydstatic.com/fanyi/newweb/v1.0.18/scripts/newweb/fanyi.min.js">http://shared.ydstatic.com/fanyi/newweb/v1.0.18/scripts/newweb/fanyi.min.js</a><br>是进行加密的JavaScript文件<br><img src= "/img/loading.gif" data-lazy-src="20190717153844373.png" alt="在这里插入图片描述"><br>我们将这个JavaScript文件,按下Ctrl+A全选,Ctrl+C进行复制,但是这个代码是压缩格式,不利于我们的阅读<br>这里小编给给大家提供了一个js格式化的网站<a href="http://tool.oschina.net/codeformat/js/">在线代码格式化</a><br>粘贴进来后,即可复制格式化好的代码<br><img src= "/img/loading.gif" data-lazy-src="20190717154346596.png" alt="在这里插入图片描述"><br>下面在PyCharm中新建一个js文件,将格式化好的js代码粘贴进来,PyCharm的安装可以参考<a href="https://blog.csdn.net/qq_40223983/article/details/95736859">PyCharm的安装以及破解</a></p><p>将代码粘贴进来后,按下Ctrl+F可以在代码中进行搜索,输入salt,逐个查看比对<br><img src= "/img/loading.gif" data-lazy-src="20190717160045237.png" alt="在这里插入图片描述"><br>但是通过我们的观察,浏览器中的data参数,版本是2.1<br><img src= "/img/loading.gif" data-lazy-src="20190717160252257.png" alt="在这里插入图片描述"><br>说明我们找的不对,继续向下搜索,只到查找到version : 2.1,这里的salt即为data中的参数<br><img src= "/img/loading.gif" data-lazy-src="20190717160404599.png" alt="在这里插入图片描述"><br>我们发现salt、sign和ts都的r的属性,下面我们搜索一下r是如何定义的<br>通过搜索,我们找到了这里<br><img src= "/img/loading.gif" data-lazy-src="20190717161152255.png" alt="在这里插入图片描述"><br>根据代码可以看出:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">r &#x3D; &quot;&quot; + (new Date).getTime()</span><br></pre></td></tr></table></figure><p>所以ts就是当前的时间戳(这里要注意:JavaScript中的时间是以毫秒为单位的,所以在下面我们生成的时候注意单位的换算)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">i &#x3D; r + parseInt(10 * Math.random(), 10);</span><br></pre></td></tr></table></figure><p>salt即为r加上一个在0-10之间的随机数</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sign: n.md5(&quot;fanyideskweb&quot; + e + i + &quot;97_3(jkMYg@T[KZQmqjTK&quot;)</span><br></pre></td></tr></table></figure><p>sign为对两个字符串加上e和i拼接的md5加密<br>其中i即为salt<br><img src= "/img/loading.gif" data-lazy-src="20190717162135404.png" alt="在这里插入图片描述"><br>而e经过上面的代码,我们可以确定为输入的字符串<br>到这里我们就将需要的加密字符确定好了</p><h2 id="实战代码"><a href="#实战代码" class="headerlink" title="实战代码"></a>实战代码</h2><p>在PyCharm中新建一个项目,建立一个py文件<br>在正式写代码之前,我们可以在程序前加上</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#!&#x2F;usr&#x2F;bin&#x2F;env python</span><br><span class="line"># -*- coding:utf-8 -*-</span><br><span class="line"># Created by 秋叶夏风</span><br></pre></td></tr></table></figure><p>第一行 指出python解释器位置,不知道的小伙伴可以参考<a href="https://www.cnblogs.com/mqxs/p/7728404.html">#!/usr/bin/python 作用</a><br>第二行 # -<em>- coding:utf-8 -</em>-的意思时指点该程序使用的utf-8编码,这个utf-8编码是干啥的呢？可以参考<a href="https://bbs.csdn.net/topics/390476205">-<em>- coding: utf-8 -</em>-的作用</a><br>(づ￣ 3￣)づ皮一下，很开心。<br>第三行不是必须要写的，可以省略。。。。</p><p>导入requests模块,代码如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import requests</span><br></pre></td></tr></table></figure><p>将Request URL复制过来</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url &#x3D; &#39;http:&#x2F;&#x2F;fanyi.youdao.com&#x2F;translate_o?smartresult&#x3D;dict&amp;smartresult&#x3D;rule&#39;</span><br></pre></td></tr></table></figure><p>将要翻译的字符输入进来</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">e &#x3D; input(&#39;please input:&#39;)</span><br></pre></td></tr></table></figure><p>下面构建请求需要的data<br>首先要构建的是ts,导入python中的时间模块</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import time</span><br></pre></td></tr></table></figure><p>生成当前的时间戳</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sjc &#x3D; time.time()</span><br></pre></td></tr></table></figure><p>转换类型和进制</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ts &#x3D; str(int(sjc*1000))</span><br></pre></td></tr></table></figure><p>下面构建salt<br>导入random模块,</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import random</span><br></pre></td></tr></table></figure><p>生成随机数并转换类型和进制</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">salt &#x3D; ts + str(int(random.random()*10))</span><br></pre></td></tr></table></figure><p>接下来是构建sign,需要用到python中的hashlib库来进行md5的加密,代码如下<br>导入模块</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import hashlib</span><br></pre></td></tr></table></figure><p>拼接字符串</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">con &#x3D; &quot;fanyideskweb&quot; + e + salt + &quot;97_3(jkMYg@T[KZQmqjTK&quot;</span><br></pre></td></tr></table></figure><p>md5加密</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sign &#x3D; hashlib.md5(con.encode(encoding&#x3D;&#39;UTF-8&#39;)).hexdigest()</span><br></pre></td></tr></table></figure><p>复制data中的内容<br><img src= "/img/loading.gif" data-lazy-src="20190717164028790.png" alt="在这里插入图片描述"><br>在PyCharm中粘贴后按下Ctrl+R可以进行替换,需要勾选Regex(正则表达式匹配模式)<br><img src= "/img/loading.gif" data-lazy-src="20190717164247442.png" alt="在这里插入图片描述"><br>匹配的正则表达式代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">^(.*): (.*)</span><br><span class="line">    &#39;$1&#39;:&#39;$2&#39;,</span><br></pre></td></tr></table></figure><p>匹配好后,将i、salt、sign和ts替换成前面生成的变量</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">data &#x3D; &#123;</span><br><span class="line">    &#39;i&#39;: e,</span><br><span class="line">    &#39;from&#39;: &#39;AUTO&#39;,</span><br><span class="line">    &#39;to&#39;: &#39;AUTO&#39;,</span><br><span class="line">    &#39;smartresult&#39;: &#39;dict&#39;,</span><br><span class="line">    &#39;client&#39;: &#39;fanyideskweb&#39;,</span><br><span class="line">    &#39;salt&#39;: salt,</span><br><span class="line">    &#39;sign&#39;: sign,</span><br><span class="line">    &#39;ts&#39;: ts,</span><br><span class="line">    &#39;bv&#39;: &#39;9c4fffad2fb69d08cd130e408e0f8108&#39;,</span><br><span class="line">    &#39;doctype&#39;: &#39;json&#39;,</span><br><span class="line">    &#39;version&#39;: &#39;2.1&#39;,</span><br><span class="line">    &#39;keyfrom&#39;: &#39;fanyi.web&#39;,</span><br><span class="line">    &#39;action&#39;: &#39;FY_BY_REALTlME&#39;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>构建headers,这里给出了三个必要的参数,不确定的小伙伴可以将请求头中的Request Headers全部复制过来也行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">header &#x3D; &#123;</span><br><span class="line">    &#39;User-Agent&#39;: &#39;Mozilla&#x2F;5.0 (Windows NT 10.0; WOW64) AppleWebKit&#x2F;537.36 (KHTML, like Gecko) Chrome&#x2F;71.0.3578.98 Safari&#x2F;537.36&#39;,</span><br><span class="line">    &#39;Referer&#39;: &#39;http:&#x2F;&#x2F;fanyi.youdao.com&#x2F;&#39;,</span><br><span class="line">    &#39;Cookie&#39;: &#39;OUTFOX_SEARCH_USER_ID&#x3D;-1154806696@10.168.8.76; OUTFOX_SEARCH_USER_ID_NCOO&#x3D;1227534676.2988937; JSESSIONID&#x3D;aaa7LDLdy4Wbh9ECJb_Vw; ___rl__test__cookies&#x3D;1563334957868&#39;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>发出请求</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">res &#x3D; requests.post(url,data&#x3D;data,headers&#x3D;header).text</span><br></pre></td></tr></table></figure><p>用正则进行匹配翻译的内容<br>导入re模块</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import re</span><br></pre></td></tr></table></figure><p>开始匹配</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rep &#x3D; re.findall(&#39;&quot;tgt&quot;:&quot;(.*?)&quot;&#39;,res,re.S)[0]</span><br></pre></td></tr></table></figure><p>输出匹配的内容</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">print(rep)</span><br></pre></td></tr></table></figure><p>经过封装,完整代码如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line">#!&#x2F;usr&#x2F;bin&#x2F;env python</span><br><span class="line"># -*- coding:utf-8 -*-</span><br><span class="line"># Created by  秋叶夏风</span><br><span class="line"></span><br><span class="line">def get_data(e):</span><br><span class="line">    &#39;&#39;&#39;</span><br><span class="line">    构建data数据函数</span><br><span class="line">    :param e: 输入要翻译的内容</span><br><span class="line">    :return: 字典类型的data数据</span><br><span class="line">    &#39;&#39;&#39;</span><br><span class="line">    import time</span><br><span class="line">    sjc &#x3D; time.time()</span><br><span class="line">    ts &#x3D; str(int(sjc * 1000))</span><br><span class="line">    import random</span><br><span class="line">    salt &#x3D; ts + str(int(random.random() * 10))</span><br><span class="line">    import hashlib</span><br><span class="line">    con &#x3D; &quot;fanyideskweb&quot; + e + salt + &quot;97_3(jkMYg@T[KZQmqjTK&quot;</span><br><span class="line">    sign &#x3D; hashlib.md5(con.encode(encoding&#x3D;&#39;UTF-8&#39;)).hexdigest()</span><br><span class="line"></span><br><span class="line">    data &#x3D; &#123;</span><br><span class="line">        &#39;i&#39;: e,</span><br><span class="line">        &#39;from&#39;: &#39;AUTO&#39;,</span><br><span class="line">        &#39;to&#39;: &#39;AUTO&#39;,</span><br><span class="line">        &#39;smartresult&#39;: &#39;dict&#39;,</span><br><span class="line">        &#39;client&#39;: &#39;fanyideskweb&#39;,</span><br><span class="line">        &#39;salt&#39;: salt,</span><br><span class="line">        &#39;sign&#39;: sign,</span><br><span class="line">        &#39;ts&#39;: ts,</span><br><span class="line">        &#39;bv&#39;: &#39;9c4fffad2fb69d08cd130e408e0f8108&#39;,</span><br><span class="line">        &#39;doctype&#39;: &#39;json&#39;,</span><br><span class="line">        &#39;version&#39;: &#39;2.1&#39;,</span><br><span class="line">        &#39;keyfrom&#39;: &#39;fanyi.web&#39;,</span><br><span class="line">        &#39;action&#39;: &#39;FY_BY_REALTlME&#39;</span><br><span class="line">    &#125;</span><br><span class="line">    return data</span><br><span class="line"></span><br><span class="line">def get_para(e):</span><br><span class="line">    &#39;&#39;&#39;</span><br><span class="line">    获取需要的参数</span><br><span class="line">    :param e: 输入字符串</span><br><span class="line">    :return:</span><br><span class="line">    &#39;&#39;&#39;</span><br><span class="line">    header &#x3D; &#123;</span><br><span class="line">        &#39;User-Agent&#39;: &#39;Mozilla&#x2F;5.0 (Windows NT 10.0; WOW64) AppleWebKit&#x2F;\</span><br><span class="line">                       537.36 (KHTML, like Gecko) Chrome&#x2F;71.0.3578.98 Safari&#x2F;537.36&#39;,</span><br><span class="line">        &#39;Cookie&#39;: &#39;OUTFOX_SEARCH_USER_ID&#x3D;-1154806696@10.168.8.76; \</span><br><span class="line">                   OUTFOX_SEARCH_USER_ID_NCOO&#x3D;1227534676.2988937; \</span><br><span class="line">                   JSESSIONID&#x3D;aaa7LDLdy4Wbh9ECJb_Vw; ___rl__test__cookies&#x3D;1563334957868&#39;,</span><br><span class="line">        &#39;Referer&#39;: &#39;http:&#x2F;&#x2F;fanyi.youdao.com&#x2F;&#39;</span><br><span class="line">    &#125;</span><br><span class="line">    return get_data(e),header</span><br><span class="line"></span><br><span class="line">def search(res):</span><br><span class="line">    &#39;&#39;&#39;</span><br><span class="line">    用于匹配响应的结果</span><br><span class="line">    :param res:</span><br><span class="line">    :return:</span><br><span class="line">    &#39;&#39;&#39;</span><br><span class="line">    import re</span><br><span class="line">    model &#x3D; &#39;&quot;tgt&quot;:&quot;(.*?)&quot;&#39;</span><br><span class="line">    rep &#x3D; re.findall(model, res, re.S)</span><br><span class="line">    rep &#x3D; rep[0]</span><br><span class="line">    return rep</span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">    import requests</span><br><span class="line">    url &#x3D; &#39;http:&#x2F;&#x2F;fanyi.youdao.com&#x2F;translate_o?smartresult&#x3D;dict&amp;smartresult&#x3D;rule&#39;</span><br><span class="line">    e &#x3D; input(&#39;please input:&#39;)</span><br><span class="line">    data &#x3D; get_para(e)[0]</span><br><span class="line">    header &#x3D; get_para(e)[1]</span><br><span class="line">    response &#x3D; requests.post(url,data&#x3D;data,headers&#x3D;header).text</span><br><span class="line">    result &#x3D; search(response)</span><br><span class="line">    print(result)</span><br><span class="line">if __name__ &#x3D;&#x3D; &#39;__main__&#39;:</span><br><span class="line">    while True:</span><br><span class="line">        main()</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> solution </tag>
            
            <tag> Python </tag>
            
            <tag> regex </tag>
            
            <tag> spider </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python基础部分索引</title>
      <link href="python/base/python-base-index/"/>
      <url>python/base/python-base-index/</url>
      
        <content type="html"><![CDATA[<h3 id="python基础"><a href="#python基础" class="headerlink" title="python基础"></a>python基础</h3><p><a href="https://blog.csdn.net/qq_40223983/article/details/95655323">python简介</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95655470">python安装以及版本检测</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95658232">python注释与语句分类</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95734668">python命令方式和关键字</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95735209">python中的变量</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95735483">python的数据类型</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95735657">python的数据类型转换</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95736028">python中的运算和运算符</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95738341">python中的流程控制</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95738390">python中的循环结构</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95761163">python中的函数</a>    </p><h3 id="python核心"><a href="#python核心" class="headerlink" title="python核心"></a>python核心</h3><p><a href="https://blog.csdn.net/qq_40223983/article/details/95888163">python中变量的作用域</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95979221">python中的内部函数和闭包函数</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95979549">python中的lambda表达式</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95980304">python中的字符串</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95981110">python中格式化字符串</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95981400">python中的内建函数</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95981687">python中的列表</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95982113">python中的元组操作</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95982387">python中的字典</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95982568">python中的集合</a>    </p><h3 id="python高级"><a href="#python高级" class="headerlink" title="python高级"></a>python高级</h3><p><a href="https://blog.csdn.net/qq_40223983/article/details/95982704">python中的文件操作</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95983081">python中的string模块</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95983295">python中的数学模块</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95983501">python中的OS模块</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95983850">python中的zip模块</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95984230">python中的shutil模块</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95984378">python中时间模块</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95987012">python中面向对象</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95988200">python中的魔术方法</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95988519">python中的装饰器和抽象类</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/95989163">python中错误和异常处理</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/96092636">python中的模块和包</a><br><a href="https://blog.csdn.net/qq_40223983/article/details/96093396">python中的tkinter模块</a>    </p>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> index </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python中的魔术方法</title>
      <link href="python/base/python-method/"/>
      <url>python/base/python-method/</url>
      
        <content type="html"><![CDATA[<h3 id="魔术方法"><a href="#魔术方法" class="headerlink" title="魔术方法"></a>魔术方法</h3><hr><blockquote><p>&#x9B54;&#x672F;&#x65B9;&#x6CD5;&#x5C31;&#x662F;&#x4E00;&#x4E2A;&#x7C7B;/&#x5BF9;&#x8C61;&#x4E2D;&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x548C;&#x666E;&#x901A;&#x65B9;&#x6CD5;&#x552F;&#x4E00;&#x7684;&#x4E0D;&#x540C;&#x65F6;&#xFF0C;&#x666E;&#x901A;&#x65B9;&#x6CD5;&#x9700;&#x8981;&#x8C03;&#x7528;&#xFF01;&#x800C;&#x9B54;&#x672F;&#x65B9;&#x6CD5;&#x662F;&#x5728;&#x7279;&#x5B9A;&#x65F6;&#x523B;&#x81EA;&#x52A8;&#x89E6;&#x53D1;&#x3002;</p></blockquote><h4 id="1init">1.__init__</h4><pre><code>&#x521D;&#x59CB;&#x5316;&#x9B54;&#x672F;&#x65B9;&#x6CD5;&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x521D;&#x59CB;&#x5316;&#x5BF9;&#x8C61;&#x65F6;&#x89E6;&#x53D1;&#xFF08;&#x4E0D;&#x662F;&#x5B9E;&#x4F8B;&#x5316;&#x89E6;&#x53D1;&#xFF0C;&#x4F46;&#x662F;&#x548C;&#x5B9E;&#x4F8B;&#x5316;&#x5728;&#x4E00;&#x4E2A;&#x64CD;&#x4F5C;&#x4E2D;&#xFF09;&#x53C2;&#x6570;&#xFF1A;&#x81F3;&#x5C11;&#x6709;&#x4E00;&#x4E2A;self&#xFF0C;&#x63A5;&#x6536;&#x5BF9;&#x8C61;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x65E0;&#x4F5C;&#x7528;&#xFF1A;&#x521D;&#x59CB;&#x5316;&#x5BF9;&#x8C61;&#x7684;&#x6210;&#x5458;&#x6CE8;&#x610F;&#xFF1A;&#x4F7F;&#x7528;&#x8BE5;&#x65B9;&#x5F0F;&#x521D;&#x59CB;&#x5316;&#x7684;&#x6210;&#x5458;&#x90FD;&#x662F;&#x76F4;&#x63A5;&#x5199;&#x5165;&#x5BF9;&#x8C61;&#x5F53;&#x4E2D;&#xFF0C;&#x7C7B;&#x4E2D;&#x65E0;&#x6CD5;&#x5177;&#x6709;</code></pre><h4 id="2new">2.__new__</h4><pre><code>&#x5B9E;&#x4F8B;&#x5316;&#x9B54;&#x672F;&#x65B9;&#x6CD5;&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A; &#x5728;&#x5B9E;&#x4F8B;&#x5316;&#x5BF9;&#x65F6;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;&#x81F3;&#x5C11;&#x4E00;&#x4E2A;cls &#x63A5;&#x6536;&#x5F53;&#x524D;&#x7C7B;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x8FD4;&#x56DE;&#x4E00;&#x4E2A;&#x5BF9;&#x8C61;&#x5B9E;&#x4F8B;&#x4F5C;&#x7528;&#xFF1A;&#x5B9E;&#x4F8B;&#x5316;&#x5BF9;&#x8C61;&#x6CE8;&#x610F;&#xFF1A;&#x5B9E;&#x4F8B;&#x5316;&#x5BF9;&#x8C61;&#x662F;Object&#x7C7B;&#x5E95;&#x5C42;&#x5B9E;&#x73B0;&#xFF0C;&#x5176;&#x4ED6;&#x7C7B;&#x7EE7;&#x627F;&#x4E86;Object&#x7684;__new__&#x624D;&#x80FD;&#x591F;&#x5B9E;&#x73B0;&#x5B9E;&#x4F8B;&#x5316;&#x5BF9;&#x8C61;&#x3002;&#x6CA1;&#x4E8B;&#x522B;&#x78B0;&#x8FD9;&#x4E2A;&#x9B54;&#x672F;&#x65B9;&#x6CD5;&#xFF0C;&#x5148;&#x89E6;&#x53D1;__new__&#x624D;&#x4F1A;&#x89E6;&#x53D1;__init__ </code></pre><h4 id="3del">3.__del__</h4><pre><code>&#x6790;&#x6784;&#x9B54;&#x672F;&#x65B9;&#x6CD5;&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x5F53;&#x5BF9;&#x8C61;&#x6CA1;&#x6709;&#x7528;&#xFF08;&#x6CA1;&#x6709;&#x4EFB;&#x4F55;&#x53D8;&#x91CF;&#x5F15;&#x7528;&#xFF09;&#x7684;&#x65F6;&#x5019;&#x88AB;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;&#x4E00;&#x4E2A;self &#x7ED3;&#x5A5A;&#x641C;&#x5BF9;&#x8C61;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x65E0;&#x4F5C;&#x7528;&#xFF1A;&#x4F7F;&#x7528;&#x5B8C;&#x5BF9;&#x8C61;&#x662F;&#x56DE;&#x6536;&#x8D44;&#x6E90;&#x6CE8;&#x610F;&#xFF1A;del&#x4E0D;&#x4E00;&#x5B9A;&#x4F1A;&#x89E6;&#x53D1;&#x5F53;&#x524D;&#x65B9;&#x6CD5;&#xFF0C;&#x53EA;&#x6709;&#x5F53;&#x524D;&#x5BF9;&#x8C61;&#x6CA1;&#x6709;&#x4EFB;&#x4F55;&#x53D8;&#x91CF;&#x63A5;&#x6536;&#x65F6;&#x624D;&#x4F1A;&#x89E6;&#x53D1;</code></pre><h4 id="4call">4.__call__</h4><pre><code>&#x8C03;&#x7528;&#x5BF9;&#x8C61;&#x7684;&#x9B54;&#x672F;&#x65B9;&#x6CD5;&#x89E6;&#x53D1;&#x65F6;&#x673A;:&#x5C06;&#x5BF9;&#x8C61;&#x5F53;&#x4F5C;&#x51FD;&#x6570;&#x8C03;&#x7528;&#x65F6;&#x89E6;&#x53D1; &#x5BF9;&#x8C61;()&#x53C2;&#x6570;:&#x81F3;&#x5C11;&#x4E00;&#x4E2A;self&#x63A5;&#x6536;&#x5BF9;&#x8C61;&#xFF0C;&#x5176;&#x4F59;&#x6839;&#x636E;&#x8C03;&#x7528;&#x65F6;&#x53C2;&#x6570;&#x51B3;&#x5B9A;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x6839;&#x636E;&#x60C5;&#x51B5;&#x800C;&#x5B9A;&#x4F5C;&#x7528;&#xFF1A;&#x53EF;&#x4EE5;&#x5C06;&#x590D;&#x6742;&#x7684;&#x6B65;&#x9AA4;&#x8FDB;&#x884C;&#x5408;&#x5E76;&#x64CD;&#x4F5C;&#xFF0C;&#x51CF;&#x5C11;&#x8C03;&#x7528;&#x7684;&#x6B65;&#x9AA4;&#xFF0C;&#x65B9;&#x4FBF;&#x4F7F;&#x7528;&#x6CE8;&#x610F;&#xFF1A;&#x65E0;</code></pre><h4 id="5len">5.__len__</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x4F7F;&#x7528;len(&#x5BF9;&#x8C61;) &#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;&#x4E00;&#x4E2A;&#x53C2;&#x6570;self&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x662F;&#x4E00;&#x4E2A;&#x6574;&#x578B;&#x4F5C;&#x7528;&#xFF1A;&#x53EF;&#x4EE5;&#x8BBE;&#x7F6E;&#x4E3A;&#x68C0;&#x6D4B;&#x5BF9;&#x8C61;&#x6210;&#x5458;&#x4E2A;&#x6570;&#xFF0C;&#x4F46;&#x662F;&#x4E5F;&#x53EF;&#x4EE5;&#x8FDB;&#x884C;&#x5176;&#x4ED6;&#x4EFB;&#x610F;&#x64CD;&#x4F5C;&#x6CE8;&#x610F;&#xFF1A;&#x8FD4;&#x56DE;&#x503C;&#x5FC5;&#x987B;&#x5FC5;&#x987B;&#x662F;&#x6574;&#x6570;&#xFF0C;&#x5426;&#x5219;&#x8BED;&#x6CD5;&#x62A5;&#x9519;&#xFF0C;&#x53E6;&#x5916;&#x8BE5;&#x8981;&#x6C42;&#x662F;&#x683C;&#x5F0F;&#x8981;&#x6C42;&#x3002;</code></pre><h4 id="6str">6.__str__</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;:&#x4F7F;&#x7528;print(&#x5BF9;&#x8C61;)&#x6216;&#x8005;str(&#x5BF9;&#x8C61;)&#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;&#x4E00;&#x4E2A;self&#x63A5;&#x6536;&#x5BF9;&#x8C61;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x662F;&#x5B57;&#x7B26;&#x4E32;&#x7C7B;&#x578B;&#x4F5C;&#x7528;&#xFF1A;print&#xFF08;&#x5BF9;&#x8C61;&#x65F6;&#xFF09;&#x8FDB;&#x884C;&#x64CD;&#x4F5C;&#xFF0C;&#x5F97;&#x5230;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x901A;&#x5E38;&#x7528;&#x4E8E;&#x5FEB;&#x6377;&#x64CD;&#x4F5C;&#x6CE8;&#x610F;&#xFF1A;&#x65E0;</code></pre><h4 id="7repr">7.__repr__</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;:&#x5728;&#x4F7F;&#x7528;repr(&#x5BF9;&#x8C61;)&#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;&#x4E00;&#x4E2A;self&#x63A5;&#x6536;&#x5BF9;&#x8C61;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x662F;&#x5B57;&#x7B26;&#x4E32;&#x4F5C;&#x7528;&#xFF1A;&#x5C06;&#x5BF9;&#x8C61;&#x8F6C;&#x4F7F;&#x7528;repr&#x5316;&#x4E3A;&#x5B57;&#x7B26;&#x4E32;&#x65F6;&#x4F7F;&#x7528;&#xFF0C;&#x4E5F;&#x53EF;&#x4EE5;&#x7528;&#x4E8E;&#x5FEB;&#x6377;&#x64CD;&#x4F5C;</code></pre><blockquote><p>repr&#x51FD;&#x6570;&#x548C;str&#x51FD;&#x6570;&#x5904;&#x7406;&#x5B57;&#x7B26;&#x4E32;&#x53EA;&#x6709;&#x4E00;&#x4E2A;&#x533A;&#x522B;&#xFF1A;</p><p>str&#x7684;&#x7ED3;&#x679C; &#x5B57;&#x7B26;&#x4E32;&#x672C;&#x8EAB; &#xFF08;&#x7ED3;&#x679C;&#x53EF;&#x4EE5;&#x88AB;eval&#x6267;&#x884C;&#xFF09;</p><p>&#x5982;&#xFF1A;x = &apos;&#x65E0;&#x56FE;&#x8A00;Diao&apos; str() -&gt;&#x65E0;&#x56FE;&#x8A00;Diao</p><p>rerpr&#x7684;&#x7ED3;&#x679C; &#x5B57;&#x7B26;&#x4E32;&#x5B9A;&#x4E49;&#x7ED3;&#x6784; &#xFF08;eavl&#x4E0D;&#x4F1A;&#x6267;&#x884C;repr&#x7ED3;&#x679C;&#xFF09;</p><p>&#x5982;&#xFF1A;x = &apos;&#x65E0;&#x56FE;&#x8A00;Diao&apos; repr() -&gt;&apos;&#x65E0;&#x56FE;&#x8A00;Diao&apos;</p><p>&#x5907;&#x6CE8;: &#x5728;&#x7C7B;&#x4E2D;&#x901A;&#x5E38;&#x60C5;&#x51B5;&#x4E0B;__str__&#x548C;__repr__ &#x8BBE;&#x7F6E;&#x76F8;&#x540C;&#x5373;&#x53EF;</p><p><strong>eval()</strong> </p><p>&#x51FD;&#x6570; &#x5C06;&#x5B57;&#x7B26;&#x4E32;&#x5F53;&#x4F5C;python&#x4EE3;&#x7801;&#x6267;&#x884C;</p><p>&#x683C;&#x5F0F;&#xFF1A;eval(&#x5B57;&#x7B26;&#x4E32;)</p><p>&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x53EF;&#x4EE5;&#x6709;&#x8FD4;&#x56DE;&#x503C;</p></blockquote><h4 id="8bool">8.__bool__</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;: &#x4F7F;&#x7528;bool(&#x5BF9;&#x8C61;)&#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;&#x4E00;&#x4E2A;self&#x63A5;&#x6536;&#x5BF9;&#x8C61;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x662F;&#x5E03;&#x5C14;&#x503C;&#x4F5C;&#x7528;&#xFF1A;&#x6839;&#x636E;&#x5B9E;&#x9645;&#x60C5;&#x51B5;&#x51B3;&#x5B9A;&#xFF0C;&#x53EF;&#x4EE5;&#x4F5C;&#x4E3A;&#x5FEB;&#x6377;&#x65B9;&#x5F0F;&#x4F7F;&#x7528;&#x6CE8;&#x610F;:&#x4EC5;&#x9002;&#x5408;&#x4E8E;&#x8FD4;&#x56DE;&#x5E03;&#x5C14;&#x503C;&#x7684;&#x64CD;&#x4F5C;</code></pre><h4 id="9format">9.__format__</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x4F7F;&#x7528;&#x5B57;&#x7B26;&#x4E32;.format(&#x5BF9;&#x8C61;)&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;&#x4E00;&#x4E2A;self&#x63A5;&#x6536;&#x5BF9;&#x8C61;&#xFF0C;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#x63A5;&#x6536;format&#x7684;&#123;&#125;&#x4E2D;&#x7684;&#x683C;&#x5F0F;&#xFF0C;&#x4F8B;&#x5982;:&gt;5&#x8FD4;&#x56DE;&#x503C;:&#x5FC5;&#x987B;&#x662F;&#x5B57;&#x7B26;&#x4E32;&#x4F5C;&#x7528;&#xFF1A;&#x8BBE;&#x7F6E;&#x5BF9;&#x8C61;&#x53EF;&#x4EE5;&#x4F5C;&#x4E3A;format&#x7684;&#x53C2;&#x6570;&#xFF0C;&#x5E76;&#x4E14;&#x81EA;&#x5B9A;&#x4E49;&#x5BF9;&#x8C61;&#x683C;&#x5F0F;&#x5316;&#x7684;&#x89C4;&#x5219;&#x6CE8;&#x610F;&#xFF1A;&#x65E0;</code></pre><h1 id="&#x63CF;&#x8FF0;&#x7B26;&#x76F8;&#x5173;&#x7684;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x63CF;&#x8FF0;&#x7B26;&#x76F8;&#x5173;&#x7684;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h1><hr><h4 id="1get">1.__get__()</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x5728;&#x83B7;&#x53D6;&#x6307;&#x5B9A;&#x63CF;&#x8FF0;&#x7B26;&#x64CD;&#x4F5C;&#x7684;&#x6210;&#x5458;&#x5C5E;&#x6027;&#x7684;&#x503C;&#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;1&#x63CF;&#x8FF0;&#x7B26;&#x5BF9;&#x8C61;&#x672C;&#x8EAB;&#xFF0C;2&#x63CF;&#x8FF0;&#x7B26;&#x63CF;&#x8FF0;&#x7684;&#x5C5E;&#x6027;&#x6240;&#x5728;&#x7684;&#x5BF9;&#x8C61;&#xFF0C;&#x63CF;&#x8FF0;&#x7B26;&#x63CF;&#x8FF0;&#x7684;&#x5BF9;&#x8C61;&#x7684;&#x7C7B;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x6709;&#xFF0C;&#x4E0D;&#x7136;&#x65E0;&#x6CD5;&#x83B7;&#x53D6;&#x76F8;&#x5E94;&#x5C5E;&#x6027;&#x503C;&#x6CE8;&#x610F;&#xFF1A;&#x4EC5;&#x5728;&#x63CF;&#x8FF0;&#x7B26;&#x4E2D;&#x4F7F;&#x7528;</code></pre><h4 id="2set">2.__set__()</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x5728;&#x8BBE;&#x7F6E;&#x6216;&#x8005;&#x6DFB;&#x52A0;&#x6307;&#x5B9A;&#x63CF;&#x8FF0;&#x7B26;&#x64CD;&#x4F5C;&#x7684;&#x6210;&#x5458;&#x5C5E;&#x6027;&#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;1&#x63CF;&#x8FF0;&#x7B26;&#x5BF9;&#x8C61;&#x672C;&#x8EAB;&#xFF0C;2&#x63CF;&#x8FF0;&#x7B26;&#x63CF;&#x8FF0;&#x7684;&#x5C5E;&#x6027;&#x6240;&#x5728;&#x7684;&#x5BF9;&#x8C61;,3&#x8981;&#x8BBE;&#x7F6E;&#x7684;&#x503C;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x65E0;&#x6CE8;&#x610F;&#xFF1A;&#x4EC5;&#x5728;&#x63CF;&#x8FF0;&#x7B26;&#x4E2D;&#x4F7F;&#x7528;</code></pre><h4 id="3delete">3.__delete__()</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x5728;&#x5220;&#x9664;&#x6307;&#x5B9A;&#x63CF;&#x8FF0;&#x7B26;&#x64CD;&#x4F5C;&#x7684;&#x6210;&#x5458;&#x5C5E;&#x6027;&#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;1&#x63CF;&#x8FF0;&#x7B26;&#x5BF9;&#x8C61;&#x672C;&#x8EAB;&#xFF0C;2&#x63CF;&#x8FF0;&#x7B26;&#x63CF;&#x8FF0;&#x7684;&#x5C5E;&#x6027;&#x6240;&#x5728;&#x7684;&#x5BF9;&#x8C61;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x65E0;&#x6CE8;&#x610F;&#xFF1A;&#x4EC5;&#x5728;&#x63CF;&#x8FF0;&#x7B26;&#x4E2D;&#x4F7F;&#x7528;</code></pre><h1 id="&#x4E0E;&#x5C5E;&#x6027;&#x64CD;&#x4F5C;&#x76F8;&#x5173;&#x7684;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x4E0E;&#x5C5E;&#x6027;&#x64CD;&#x4F5C;&#x76F8;&#x5173;&#x7684;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h1><hr><h4 id="1getattr&#xFF08;&#xFF09;">1.__getattr__&#xFF08;&#xFF09;</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x83B7;&#x53D6;&#x4E0D;&#x5B58;&#x5728;&#x7684;&#x5BF9;&#x8C61;&#x6210;&#x5458;&#x65F6;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;1&#x63A5;&#x6536;&#x5F53;&#x524D;&#x5BF9;&#x8C61;&#x7684;self&#xFF0C;&#x4E00;&#x4E2A;&#x662F;&#x83B7;&#x53D6;&#x6210;&#x5458;&#x540D;&#x79F0;&#x7684;&#x5B57;&#x7B26;&#x4E32;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x6709;&#x503C;&#x4F5C;&#x7528;:&#x4E3A;&#x8BBF;&#x95EE;&#x4E0D;&#x5B58;&#x5728;&#x7684;&#x5C5E;&#x6027;&#x8BBE;&#x7F6E;&#x503C;&#x6CE8;&#x610F;&#xFF1A;getattribute&#x65E0;&#x8BBA;&#x4F55;&#x65F6;&#x90FD;&#x4F1A;&#x5728;getattr&#x4E4B;&#x524D;&#x89E6;&#x53D1;&#xFF0C;&#x89E6;&#x53D1;&#x4E86;getattribute&#x5C31;&#x4E0D;&#x4F1A;&#x5728;&#x89E6;&#x53D1;getattr&#x4E86;</code></pre><h4 id="2setattr&#xFF08;&#xFF09;">2.__setattr__&#xFF08;&#xFF09;</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;:&#x8BBE;&#x7F6E;&#x5BF9;&#x8C61;&#x6210;&#x5458;&#x503C;&#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;:1&#x4E2A;&#x5F53;&#x524D;&#x5BF9;&#x8C61;&#x7684;self,&#x4E00;&#x4E2A;&#x662F;&#x8981;&#x8BBE;&#x7F6E;&#x7684;&#x6210;&#x5458;&#x540D;&#x79F0;&#x5B57;&#x7B26;&#x4E32;,&#x4E00;&#x4E2A;&#x662F;&#x8981;&#x8BBE;&#x7F6E;&#x7684;&#x503C;&#x8FD4;&#x56DE;&#x503C;:&#x65E0; &#x8FC7;&#x7A0B;&#x64CD;&#x4F5C;&#x4F5C;&#x7528;:&#x63A5;&#x7BA1;&#x8BBE;&#x7F6E;&#x64CD;&#x4F5C;,&#x53EF;&#x4EE5;&#x5728;&#x8BBE;&#x7F6E;&#x524D;&#x4E4B;&#x524D;&#x8FDB;&#x884C;&#x5224;&#x65AD;&#x9A8C;&#x8BC1;&#x7B49;&#x884C;&#x4E3A;&#x6CE8;&#x610F;:&#x5728;&#x5F53;&#x524D;&#x65B9;&#x6CD5;&#x4E2D;&#x65E0;&#x6CD5;&#x4F7F;&#x7528;&#x6210;&#x5458;=&#x503C;&#x7684;&#x65B9;&#x5F0F;&#x76F4;&#x63A5;&#x8BBE;&#x7F6E;&#x6210;&#x5458;&#xFF0C;&#x5426;&#x5219;&#x4F1A;&#x65E0;&#x9650;&#x9012;&#x5F52;&#xFF0C;&#x5FC5;&#x987B;&#x501F;&#x52A9;object&#x7684;&#x8BBE;&#x7F6E;&#x65B9;&#x6CD5;&#x6765;&#x5B8C;&#x6210;<p>object.<strong>setattr</strong>&#xFF08;&#x53C2;&#x6570;1&#xFF0C;&#x53C2;&#x6570;2&#xFF0C;&#x53C2;&#x6570;3&#xFF09;<br></code></pre><h4 id="3deleteattr&#xFF08;&#xFF09;">3.<strong>delattr</strong>&#xFF08;&#xFF09;</h4></p><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x5220;&#x9664;&#x5BF9;&#x8C61;&#x6210;&#x5458;&#x65F6;&#x89E6;&#x53D1;&#x53C2;&#x6570;&#xFF1A;&#x4E00;&#x4E2A;&#x5F53;&#x524D;&#x5BF9;&#x8C61;&#x7684;self&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x65E0;&#x4F5C;&#x7528;:&#x53EF;&#x4EE5;&#x5728;&#x5220;&#x9664;&#x6210;&#x5458;&#x65F6;&#x8FDB;&#x884C;&#x9A8C;&#x8BC1;&#x3002;</code></pre><h4 id="4getattribute&#xFF08;&#xFF09;">4.__getattribute__&#xFF08;&#xFF09;</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x4F7F;&#x7528;&#x5BF9;&#x8C61;&#x6210;&#x5458;&#x65F6;&#x89E6;&#x53D1;&#xFF0C;&#x65E0;&#x8BBA;&#x6210;&#x5458;&#x662F;&#x5426;&#x5B58;&#x5728;&#x53C2;&#x6570;&#xFF1A;1&#x4E2A;&#x63A5;&#x6536;&#x5F53;&#x524D;&#x5BF9;&#x8C61;self&#xFF0C;&#x4E00;&#x4E2A;&#x662F;&#x83B7;&#x53D6;&#x7684;&#x6210;&#x5458;&#x7684;&#x540D;&#x79F0;&#x5B57;&#x7B26;&#x4E32;&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x6709;&#x4F5C;&#x7528;&#xFF1A;&#x5728;&#x5177;&#x6709;&#x5C01;&#x88C5;&#x64CD;&#x4F5C;&#xFF08;&#x79C1;&#x6709;&#x5316;&#x65F6;&#xFF09;&#xFF0C;&#x4E3A;&#x7A0B;&#x5E8F;&#x5F00;&#x90E8;&#x5206;&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x4F7F;&#x7528;</code></pre><h4 id="5dir&#xFF08;&#xFF09;">5.__dir__&#xFF08;&#xFF09;</h4><pre><code>&#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;dir&#xFF08;&#x5BF9;&#x8C61;&#xFF09;&#x7684;&#x65F6;&#x5019;&#x89E6;&#x53D1;&#x53C2;&#x6570;:1&#x4E2A;&#x63A5;&#x6536;&#x5F53;&#x524D;&#x5BF9;&#x8C61;self&#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x5FC5;&#x987B;&#x4E3A;&#x5E8F;&#x5217;&#x7C7B;&#x578B;&#xFF08;&#x5217;&#x8868;&#xFF0C;&#x5143;&#x7EC4;&#xFF0C;&#x96C6;&#x5408;&#x7B49;&#xFF0C;&#xFF09;&#x4F5C;&#x7528;&#xFF1A;&#x53EF;&#x4EE5;&#x81EA;&#x5B9A;&#x4E49;&#x6210;&#x5458;&#x5217;&#x8868;&#x7684;&#x8FD4;&#x56DE;&#x503C;</code></pre><h1 id="&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;&#x4E0A;&#x5E1D;&#x6A21;&#x5F0F;">&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;(&#x4E0A;&#x5E1D;&#x6A21;&#x5F0F;)</h1><hr><h2 id="&#x6BD4;&#x8F83;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x6BD4;&#x8F83;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h2><hr><h4 id="1lt">1.__lt__()</h4><pre><code>&#x683C;&#x5F0F;&#xFF1A;    def __lt__(self,other):    return &#x6570;&#x636E;<p>&#x7279;&#x5F81;&#xFF1A;<br>    &#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x8FDB;&#x884C;&#x5C0F;&#x4E8E;&#x5224;&#x65AD;&#x65F6;&#x81EA;&#x52A8;&#x89E6;&#x53D1;<br>    &#x53C2;&#x6570;&#xFF1A;2&#x4E2A;&#x53C2;&#x6570;&#x7B2C;&#x4E00;&#x4E2A;&#x662F;self&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x5224;&#x65AD;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x5BF9;&#x8C61;<br>    &#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x8FD4;&#x56DE;&#x503C;&#x53EF;&#x4EE5;&#x4EFB;&#x610F;&#x7C7B;&#x578B;&#xFF0C;&#x63A8;&#x8350;&#x5E03;&#x5C14;&#x503C;<br>    &#x4F5C;&#x7528;&#xFF1A;&#x5B9A;&#x4E49;&#x5C0F;&#x4E8E;&#x53F7;&#x7684;&#x884C;&#x4E3A;&#xFF1A;x &lt; y &#x8C03;&#x7528; x.lt(y)<br></code></pre><h4 id="2le">2.<strong>le</strong>()</h4></p><pre><code>&#x683C;&#x5F0F;&#xFF1A;    def __le__(self):    return str&#x7279;&#x5F81;&#xFF1A;    &#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x8FDB;&#x884C;&#x5C0F;&#x4E8E;&#x7B49;&#x4E8E;&#x5224;&#x65AD;&#x65F6;&#x81EA;&#x52A8;&#x89E6;&#x53D1;    &#x53C2;&#x6570;&#xFF1A;2&#x4E2A;&#x53C2;&#x6570;&#x7B2C;&#x4E00;&#x4E2A;&#x662F;self&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x5224;&#x65AD;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x5BF9;&#x8C61;    &#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x8FD4;&#x56DE;&#x503C;&#x53EF;&#x4EE5;&#x4EFB;&#x610F;&#x7C7B;&#x578B;&#xFF0C;&#x63A8;&#x8350;&#x5E03;&#x5C14;&#x503C;    &#x4F5C;&#x7528;&#xFF1A;&#x5B9A;&#x4E49;&#x5C0F;&#x4E8E;&#x7B49;&#x4E8E;&#x53F7;&#x7684;&#x884C;&#x4E3A;&#xFF1A;x &lt;= y &#x8C03;&#x7528; x.le(y)</code></pre><h4 id="3gt">3.__gt__()</h4><pre><code>&#x683C;&#x5F0F;&#xFF1A;    def __gt__(self):    return str&#x7279;&#x5F81;&#xFF1A;    &#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x8FDB;&#x884C;&#x5927;&#x4E8E;&#x5224;&#x65AD;&#x65F6;&#x81EA;&#x52A8;&#x89E6;&#x53D1;    &#x53C2;&#x6570;&#xFF1A;2&#x4E2A;&#x53C2;&#x6570;&#x7B2C;&#x4E00;&#x4E2A;&#x662F;self&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x5224;&#x65AD;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x5BF9;&#x8C61;    &#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x8FD4;&#x56DE;&#x503C;&#x53EF;&#x4EE5;&#x4EFB;&#x610F;&#x7C7B;&#x578B;&#xFF0C;&#x63A8;&#x8350;&#x5E03;&#x5C14;&#x503C;    &#x4F5C;&#x7528;&#xFF1A;&#x5B9A;&#x4E49;&#x5927;&#x4E8E;&#x53F7;&#x7684;&#x884C;&#x4E3A;&#xFF1A;x &gt; y &#x8C03;&#x7528; x.gt(y)</code></pre><h4 id="4ge">4.__ge__()</h4><pre><code>&#x683C;&#x5F0F;&#xFF1A;    def __ge__(self):    return str&#x7279;&#x5F81;&#xFF1A;    &#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x8FDB;&#x884C;&#x5927;&#x4E8E;&#x7B49;&#x4E8E;&#x5224;&#x65AD;&#x65F6;&#x81EA;&#x52A8;&#x89E6;&#x53D1;    &#x53C2;&#x6570;&#xFF1A;2&#x4E2A;&#x53C2;&#x6570;&#x7B2C;&#x4E00;&#x4E2A;&#x662F;self&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x5224;&#x65AD;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x5BF9;&#x8C61;    &#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x8FD4;&#x56DE;&#x503C;&#x53EF;&#x4EE5;&#x4EFB;&#x610F;&#x7C7B;&#x578B;&#xFF0C;&#x63A8;&#x8350;&#x5E03;&#x5C14;&#x503C;    &#x4F5C;&#x7528;&#xFF1A;&#x5B9A;&#x4E49;&#x5927;&#x4E8E;&#x7B49;&#x4E8E;&#x53F7;&#x7684;&#x884C;&#x4E3A;&#xFF1A;x &gt;= y &#x8C03;&#x7528; x.ge(y)</code></pre><h4 id="5eq">5.__eq__()</h4><pre><code>&#x683C;&#x5F0F;&#xFF1A;    def __eq__(self):    return str&#x7279;&#x5F81;&#xFF1A;    &#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x8FDB;&#x884C;&#x7B49;&#x4E8E;&#x5224;&#x65AD;&#x65F6;&#x81EA;&#x52A8;&#x89E6;&#x53D1;    &#x53C2;&#x6570;&#xFF1A;2&#x4E2A;&#x53C2;&#x6570;&#x7B2C;&#x4E00;&#x4E2A;&#x662F;self&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x5224;&#x65AD;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x5BF9;&#x8C61;    &#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x8FD4;&#x56DE;&#x503C;&#x53EF;&#x4EE5;&#x4EFB;&#x610F;&#x7C7B;&#x578B;&#xFF0C;&#x63A8;&#x8350;&#x5E03;&#x5C14;&#x503C;    &#x4F5C;&#x7528;&#xFF1A;&#x5B9A;&#x4E49;&#x5927;&#x4E8E;&#x7B49;&#x4E8E;&#x53F7;&#x7684;&#x884C;&#x4E3A;&#xFF1A;x == y &#x8C03;&#x7528; x.eq(y)</code></pre><h4 id="6ne">6.__ne__()</h4><pre><code>&#x683C;&#x5F0F;&#xFF1A;    def __ne__(self):    return str&#x7279;&#x5F81;&#xFF1A;    &#x89E6;&#x53D1;&#x65F6;&#x673A;&#xFF1A;&#x8FDB;&#x884C;&#x4E0D;&#x7B49;&#x4E8E;&#x5224;&#x65AD;&#x65F6;&#x81EA;&#x52A8;&#x89E6;&#x53D1;    &#x53C2;&#x6570;&#xFF1A;2&#x4E2A;&#x53C2;&#x6570;&#x7B2C;&#x4E00;&#x4E2A;&#x662F;self&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x5224;&#x65AD;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x5BF9;&#x8C61;    &#x8FD4;&#x56DE;&#x503C;&#xFF1A;&#x8FD4;&#x56DE;&#x503C;&#x53EF;&#x4EE5;&#x4EFB;&#x610F;&#x7C7B;&#x578B;&#xFF0C;&#x63A8;&#x8350;&#x5E03;&#x5C14;&#x503C;    &#x4F5C;&#x7528;&#xFF1A;&#x5B9A;&#x4E49;&#x4E0D;&#x7B49;&#x53F7;&#x7684;&#x884C;&#x4E3A;&#xFF1A;x != y &#x8C03;&#x7528; x.ne(y)</code></pre><h2 id="&#x7B97;&#x672F;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x7B97;&#x672F;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h2><hr><pre><code>__add__(self, other)           &#x5B9A;&#x4E49;&#x52A0;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;+__sub__(self, other)           &#x5B9A;&#x4E49;&#x51CF;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;-__mul__(self, other)           &#x5B9A;&#x4E49;&#x4E58;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;__truediv__(self, other)       &#x5B9A;&#x4E49;&#x771F;&#x9664;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;/__floordiv__(self, other)      &#x5B9A;&#x4E49;&#x6574;&#x6570;&#x9664;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;//__mod__(self, other)           &#x5B9A;&#x4E49;&#x53D6;&#x6A21;&#x7B97;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;%__divmod__(self, other)        &#x5B9A;&#x4E49;&#x5F53;&#x88AB; divmod() &#x8C03;&#x7528;&#x65F6;&#x7684;&#x884C;&#x4E3A;__pow__(self, other[, modulo]) &#x5B9A;&#x4E49;&#x5F53;&#x88AB; power() &#x8C03;&#x7528;&#x6216; ** &#x8FD0;&#x7B97;&#x65F6;&#x7684;&#x884C;&#x4E3A;__lshift__(self, other)        &#x5B9A;&#x4E49;&#x6309;&#x4F4D;&#x5DE6;&#x79FB;&#x4F4D;&#x7684;&#x884C;&#x4E3A;&#xFF1A;&lt;&lt;__rshift__(self, other)        &#x5B9A;&#x4E49;&#x6309;&#x4F4D;&#x53F3;&#x79FB;&#x4F4D;&#x7684;&#x884C;&#x4E3A;&#xFF1A;&gt;&gt;__and__(self, other)           &#x5B9A;&#x4E49;&#x6309;&#x4F4D;&#x4E0E;&#x64CD;&#x4F5C;&#x7684;&#x884C;&#x4E3A;&#xFF1A;&amp;__xor__(self, other)           &#x5B9A;&#x4E49;&#x6309;&#x4F4D;&#x5F02;&#x6216;&#x64CD;&#x4F5C;&#x7684;&#x884C;&#x4E3A;&#xFF1A;^__or__(self, other)            &#x5B9A;&#x4E49;&#x6309;&#x4F4D;&#x6216;&#x64CD;&#x4F5C;&#x7684;&#x884C;&#x4E3A;&#xFF1A;|</code></pre><h2 id="&#x53CD;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x53CD;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h2><hr><pre><code>__radd__(self, other)      &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rsub__(self, other)      &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rmul__(self, other)      &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rtruediv__(self, other)  &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rfloordiv__(self, other) &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rmod__(self, other)      &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rdivmod__(self, other)   &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rpow__(self, other)      &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rlshift__(self, other)   &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rrshift__(self, other)   &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rand__(self, other)      &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__rxor__(self, other)      &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;__ror__(self, other)       &#x4E0E;&#x4E0A;&#x65B9;&#x76F8;&#x540C;&#xFF0C;&#x5F53;&#x5DE6;&#x64CD;&#x4F5C;&#x6570;&#x4E0D;&#x652F;&#x6301;&#x76F8;&#x5E94;&#x7684;&#x64CD;&#x4F5C;&#x65F6;&#x88AB;&#x8C03;&#x7528;</code></pre><h2 id="&#x8D4B;&#x503C;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x8D4B;&#x503C;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h2><hr><pre><code>__iadd__(self, other)             &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x52A0;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;+=__isub__(self, other)             &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x51CF;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;-=__imul__(self, other)             &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x4E58;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;=__itruediv__(self, other)         &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x771F;&#x9664;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;/=__ifloordiv__(self, other)        &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x6574;&#x6570;&#x9664;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;//=__imod__(self, other)             &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x53D6;&#x6A21;&#x7B97;&#x6CD5;&#x7684;&#x884C;&#x4E3A;&#xFF1A;%=__ipow__(self, other[, modulo])   &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x5E42;&#x8FD0;&#x7B97;&#x7684;&#x884C;&#x4E3A;&#xFF1A;**=__ilshift__(self, other)          &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x6309;&#x4F4D;&#x5DE6;&#x79FB;&#x4F4D;&#x7684;&#x884C;&#x4E3A;&#xFF1A;&lt;&lt;=__irshift__(self, other)          &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x6309;&#x4F4D;&#x53F3;&#x79FB;&#x4F4D;&#x7684;&#x884C;&#x4E3A;&#xFF1A;&gt;&gt;=__iand__(self, other)             &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x6309;&#x4F4D;&#x4E0E;&#x64CD;&#x4F5C;&#x7684;&#x884C;&#x4E3A;&#xFF1A;&amp;=__ixor__(self, other)             &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x6309;&#x4F4D;&#x5F02;&#x6216;&#x64CD;&#x4F5C;&#x7684;&#x884C;&#x4E3A;&#xFF1A;^=__ior__(self, other)              &#x5B9A;&#x4E49;&#x8D4B;&#x503C;&#x6309;&#x4F4D;&#x6216;&#x64CD;&#x4F5C;&#x7684;&#x884C;&#x4E3A;&#xFF1A;|=</code></pre><h2 id="&#x4E00;&#x5143;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x4E00;&#x5143;&#x8FD0;&#x7B97;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h2><hr><pre><code>__pos__(self)      &#x5B9A;&#x4E49;&#x6B63;&#x53F7;&#x7684;&#x884C;&#x4E3A;&#xFF1A;+x__neg__(self)      &#x5B9A;&#x4E49;&#x8D1F;&#x53F7;&#x7684;&#x884C;&#x4E3A;&#xFF1A;-x__abs__(self)      &#x5B9A;&#x4E49;&#x5F53;&#x88AB; abs() &#x8C03;&#x7528;&#x65F6;&#x7684;&#x884C;&#x4E3A;__invert__(self)   &#x5B9A;&#x4E49;&#x6309;&#x4F4D;&#x6C42;&#x53CD;&#x7684;&#x884C;&#x4E3A;&#xFF1A;~x</code></pre><h2 id="&#x7C7B;&#x578B;&#x8F6C;&#x6362;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;-jiang">&#x7C7B;&#x578B;&#x8F6C;&#x6362;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5; JIANG</h2><hr><pre><code>__complex__(self)      &#x5B9A;&#x4E49;&#x5F53;&#x88AB; complex() &#x8C03;&#x7528;&#x65F6;&#x7684;&#x884C;&#x4E3A;&#xFF08;&#x9700;&#x8981;&#x8FD4;&#x56DE;&#x6070;&#x5F53;&#x7684;&#x503C;&#xFF09;__int__(self)          &#x5B9A;&#x4E49;&#x5F53;&#x88AB; int() &#x8C03;&#x7528;&#x65F6;&#x7684;&#x884C;&#x4E3A;&#xFF08;&#x9700;&#x8981;&#x8FD4;&#x56DE;&#x6070;&#x5F53;&#x7684;&#x503C;&#xFF09;__float__(self)        &#x5B9A;&#x4E49;&#x5F53;&#x88AB; float() &#x8C03;&#x7528;&#x65F6;&#x7684;&#x884C;&#x4E3A;&#xFF08;&#x9700;&#x8981;&#x8FD4;&#x56DE;&#x6070;&#x5F53;&#x7684;&#x503C;&#xFF09;__round__(self[, n])   &#x5B9A;&#x4E49;&#x5F53;&#x88AB; round() &#x8C03;&#x7528;&#x65F6;&#x7684;&#x884C;&#x4E3A;&#xFF08;&#x9700;&#x8981;&#x8FD4;&#x56DE;&#x6070;&#x5F53;&#x7684;&#x503C;&#xFF09;__index(self)__        1. &#x5F53;&#x5BF9;&#x8C61;&#x662F;&#x88AB;&#x5E94;&#x7528;&#x5728;&#x5207;&#x7247;&#x8868;&#x8FBE;&#x5F0F;&#x4E2D;&#x65F6;&#xFF0C;&#x5B9E;&#x73B0;&#x6574;&#x5F62;&#x5F3A;&#x5236;&#x8F6C;&#x6362;                       2. &#x5982;&#x679C;&#x4F60;&#x5B9A;&#x4E49;&#x4E86;&#x4E00;&#x4E2A;&#x53EF;&#x80FD;&#x5728;&#x5207;&#x7247;&#x65F6;&#x7528;&#x5230;&#x7684;&#x5B9A;&#x5236;&#x7684;&#x6570;&#x503C;&#x578B;,&#x4F60;&#x5E94;&#x8BE5;&#x5B9A;&#x4E49; index                       3. &#x5982;&#x679C; index &#x88AB;&#x5B9A;&#x4E49;&#xFF0C;&#x5219; int &#x4E5F;&#x9700;&#x8981;&#x88AB;&#x5B9A;&#x4E49;&#xFF0C;&#x4E14;&#x8FD4;&#x56DE;&#x76F8;&#x540C;&#x7684;&#x503C;</code></pre><h2 id="&#x4E0A;&#x4E0B;&#x6587;&#x7BA1;&#x7406;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x4E0A;&#x4E0B;&#x6587;&#x7BA1;&#x7406;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h2><hr><p><strong>__enter__()</strong> &#x548C; <strong>__exit__()</strong></p><pre><code>enter(self)    1. &#x5B9A;&#x4E49;&#x5F53;&#x4F7F;&#x7528; with &#x8BED;&#x53E5;&#x65F6;&#x7684;&#x521D;&#x59CB;&#x5316;&#x884C;&#x4E3A;    2. enter &#x7684;&#x8FD4;&#x56DE;&#x503C;&#x88AB; with &#x8BED;&#x53E5;&#x7684;&#x76EE;&#x6807;&#x6216;&#x8005; as &#x540E;&#x7684;&#x540D;&#x5B57;&#x7ED1;&#x5B9A;<p>exit(self, exctype, excvalue, traceback)<br>    1. &#x5B9A;&#x4E49;&#x5F53;&#x4E00;&#x4E2A;&#x4EE3;&#x7801;&#x5757;&#x88AB;&#x6267;&#x884C;&#x6216;&#x8005;&#x7EC8;&#x6B62;&#x540E;&#x4E0A;&#x4E0B;&#x6587;&#x7BA1;&#x7406;&#x5668;&#x5E94;&#x8BE5;&#x505A;&#x4EC0;&#x4E48;<br>    2. &#x4E00;&#x822C;&#x88AB;&#x7528;&#x6765;&#x5904;&#x7406;&#x5F02;&#x5E38;&#xFF0C;&#x6E05;&#x9664;&#x5DE5;&#x4F5C;&#x6216;&#x8005;&#x505A;&#x4E00;&#x4E9B;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;&#x5B8C;&#x6BD5;&#x4E4B;&#x540E;&#x7684;&#x65E5;&#x5E38;&#x5DE5;&#x4F5C;<br></code></pre><h2 id="&#x5BB9;&#x5668;&#x7C7B;&#x578B;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;">&#x5BB9;&#x5668;&#x7C7B;&#x578B;&#x76F8;&#x5173;&#x9B54;&#x672F;&#x65B9;&#x6CD5;</h2></p><hr><pre><code>__len__(self)                  &#x5B9A;&#x4E49;&#x5F53;&#x88AB; len() &#x8C03;&#x7528;&#x65F6;&#x7684;&#x884C;&#x4E3A;&#xFF08;&#x8FD4;&#x56DE;&#x5BB9;&#x5668;&#x4E2D;&#x5143;&#x7D20;&#x7684;&#x4E2A;&#x6570;&#xFF09;__getitem__(self, key)         &#x5B9A;&#x4E49;&#x83B7;&#x53D6;&#x5BB9;&#x5668;&#x4E2D;&#x6307;&#x5B9A;&#x5143;&#x7D20;&#x7684;&#x884C;&#x4E3A;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E; self[key]__setitem__(self, key, value)  &#x5B9A;&#x4E49;&#x8BBE;&#x7F6E;&#x5BB9;&#x5668;&#x4E2D;&#x6307;&#x5B9A;&#x5143;&#x7D20;&#x7684;&#x884C;&#x4E3A;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E; self[key] = value__delitem__(self, key)         &#x5B9A;&#x4E49;&#x5220;&#x9664;&#x5BB9;&#x5668;&#x4E2D;&#x6307;&#x5B9A;&#x5143;&#x7D20;&#x7684;&#x884C;&#x4E3A;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E; del self[key]__iter__(self)                 &#x5B9A;&#x4E49;&#x5F53;&#x8FED;&#x4EE3;&#x5BB9;&#x5668;&#x4E2D;&#x7684;&#x5143;&#x7D20;&#x7684;&#x884C;&#x4E3A;__reversed__(self)             &#x5B9A;&#x4E49;&#x5F53;&#x88AB; reversed() &#x8C03;&#x7528;&#x65F6;&#x7684;&#x884C;&#x4E3A;__contains__(self, item)       &#x5B9A;&#x4E49;&#x5F53;&#x4F7F;&#x7528;&#x6210;&#x5458;&#x6D4B;&#x8BD5;&#x8FD0;&#x7B97;&#x7B26;&#xFF08;in &#x6216; not in&#xFF09;&#x65F6;&#x7684;&#x884C;&#x4E3A;</code></pre>                                        ]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python3中的re正则</title>
      <link href="python/base/python-re/"/>
      <url>python/base/python-re/</url>
      
        <content type="html"><![CDATA[<h3 id="Python3-正则表达式"><a href="#Python3-正则表达式" class="headerlink" title="Python3 正则表达式"></a>Python3 正则表达式</h3><p>正则表达式是一个特殊的字符序列，它能帮助你方便的检查一个字符串是否与某种模式匹配。</p><p>Python 自1.5版本起增加了re 模块，它提供 Perl 风格的正则表达式模式。</p><p>re 模块使 Python 语言拥有全部的正则表达式功能。</p><p>compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。</p><p>re 模块也提供了与这些方法功能完全一致的函数，这些函数使用一个模式字符串做为它们的第一个参数。</p><p>本章节主要介绍Python中常用的正则表达式处理函数。</p><h3 id="re-match函数"><a href="#re-match函数" class="headerlink" title="re.match函数"></a>re.match函数</h3><p>re.match 尝试从字符串的起始位置匹配一个模式，如果不是起始位置匹配成功的话，match()就返回none。</p><h4 id="函数语法："><a href="#函数语法：" class="headerlink" title="函数语法："></a>函数语法：</h4><p><code>re.match(pattern, string, flags=0)</code></p><h4 id="函数参数说明："><a href="#函数参数说明：" class="headerlink" title="函数参数说明："></a>函数参数说明：</h4><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>pattern</td><td>匹配的正则表达式</td></tr><tr><td>string</td><td>要匹配的字符串。</td></tr><tr><td>flags</td><td>标志位，用于控制正则表达式的匹配方式</td></tr></tbody></table><p>匹配成功re.match方法返回一个匹配的对象，否则返回None。</p><p>我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。</p><table><thead><tr><th>匹配对象方法</th><th>描述</th></tr></thead><tbody><tr><td>group(num=0)</td><td>匹配的整个表达式的字符串，group()可以一次输入多个组号，在这种情况下它将返回一个包含那些组所对应值的元组。</td></tr><tr><td>groups()</td><td>返回一个包含所有小组字符串的元组，从 1 到 所含的小组号。</td></tr></tbody></table><p>实例 1：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line">print(re.match(<span class="string">&#x27;vic&#x27;</span>, <span class="string">&#x27;victorfengming.github.io&#x27;</span>).span())  <span class="comment"># 在起始位置匹配</span></span><br><span class="line">print(re.match(<span class="string">&#x27;io&#x27;</span>, <span class="string">&#x27;victorfengming.github.io&#x27;</span>))         <span class="comment"># 不在起始位置匹配</span></span><br></pre></td></tr></table></figure><p>以上实例运行输出结果为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(0, 3)</span><br><span class="line">None</span><br></pre></td></tr></table></figure><p>实例 2：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python3</span></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line">line = <span class="string">&quot;Cats are smarter than dogs&quot;</span></span><br><span class="line"></span><br><span class="line">matchObj = re.match( <span class="string">r&#x27;(.*) are (.*?) .*&#x27;</span>, line, re.M|re.I)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> matchObj:</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;matchObj.group() : &quot;</span>, matchObj.group())</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;matchObj.group(1) : &quot;</span>, matchObj.group(<span class="number">1</span>))</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;matchObj.group(2) : &quot;</span>, matchObj.group(<span class="number">2</span>))</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;No match!!&quot;</span>)</span><br></pre></td></tr></table></figure><p>以上实例执行结果如下：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">matchObj.group() :  Cats are smarter than dogs</span><br><span class="line">matchObj.group(<span class="number">1</span>) :  Cats</span><br><span class="line">matchObj.group(<span class="number">2</span>) :  smarter</span><br></pre></td></tr></table></figure><hr><h3 id="re-search方法"><a href="#re-search方法" class="headerlink" title="re.search方法"></a>re.search方法</h3><p>re.search扫描整个字符串并且返回第一个成功的匹配<br>函数语法：<br>re.search(pattern, string, flags=0)<br>函数参数说明：  </p><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>pattern</td><td>匹配的正则表达式</td></tr><tr><td>string</td><td>要匹配的字符串</td></tr><tr><td>flags</td><td>标志位，用于控制正则表达式的匹配方式，如：是否区分大小写，多行匹配等等。</td></tr></tbody></table><p>匹配成功re.search方法返回一个匹配的对象，否则返回None<br>我们可以使用group(num)或groups()匹配对象函数来获取匹配表达式。  </p><p>|匹配对象的方法|描述|<br>|group(num=0)|匹配的整个表达式的字符串，group()可以一次输入多个组号，在这种情况下它将返回一个包含那些组所对应值的元组。|<br>|groups()|返回一个包含所有小组字符串的元组从1到所含的小组号码<br>实例1：  </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python3</span></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="comment"># 在起始位置匹配</span></span><br><span class="line">print(re.search(<span class="string">&#x27;vic&#x27;</span>,<span class="string">&quot;victorfengming.github.io&quot;</span> ).span())</span><br><span class="line"><span class="comment"># 不在起始位置匹配</span></span><br><span class="line">print(re.search(<span class="string">&#x27;io&#x27;</span>,<span class="string">&#x27;victorfengming.github.io&#x27;</span>))</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>以上实例输出结果为：<br>(0,3)<br>(14,16)</p><p>实例2：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python3</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line">line = <span class="string">&quot;Cats are smarter than dogs&quot;</span>;</span><br><span class="line"></span><br><span class="line">searchObj = re.search( <span class="string">r&#x27;(.*) are (.*?) .*&#x27;</span>, line, re.M|re.I)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> searchObj:</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;searchObj.group() : &quot;</span>, searchObj.group())</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;searchObj.group(1) : &quot;</span>, searchObj.group(<span class="number">1</span>))</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;searchObj.group(2) : &quot;</span>, searchObj.group(<span class="number">2</span>))</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;Nothing found!!&quot;</span>)</span><br></pre></td></tr></table></figure><p>以上实例执行结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">searchObj.group() :  Cats are smarter than dogs</span><br><span class="line">searchObj.group(1) :  Cats</span><br><span class="line">searchObj.group(2) :  smarter</span><br></pre></td></tr></table></figure><h3 id="re-match与re-search的区别"><a href="#re-match与re-search的区别" class="headerlink" title="re.match与re.search的区别"></a>re.match与re.search的区别</h3><p>re.match只匹配字符串的开始，如果字符串开始不符合正则表达式，则匹配失败，函数返回None；而re.search匹配整个字符串，直到找到一个匹配。<br>实例：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python3</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line">line = <span class="string">&quot;Cats are smarter than dogs&quot;</span>;</span><br><span class="line"></span><br><span class="line">matchObj = re.match( <span class="string">r&#x27;dogs&#x27;</span>, line, re.M|re.I)</span><br><span class="line"><span class="keyword">if</span> matchObj:</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;match --&gt; matchObj.group() : &quot;</span>, matchObj.group())</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;No match!!&quot;</span>)</span><br><span class="line"></span><br><span class="line">matchObj = re.search( <span class="string">r&#x27;dogs&#x27;</span>, line, re.M|re.I)</span><br><span class="line"><span class="keyword">if</span> matchObj:</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;search --&gt; matchObj.group() : &quot;</span>, matchObj.group())</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">   <span class="built_in">print</span> (<span class="string">&quot;No match!!&quot;</span>)</span><br></pre></td></tr></table></figure><p>以上实例运行结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">No match!!</span><br><span class="line">search --&gt; matchObj.group() :  dogs</span><br></pre></td></tr></table></figure><h3 id="检索和替换"><a href="#检索和替换" class="headerlink" title="检索和替换"></a>检索和替换</h3><p>Python 的re模块提供了re.sub用于替换字符串中的匹配项。</p><p>语法：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">re.sub(pattern, repl, string, max&#x3D;0)</span><br></pre></td></tr></table></figure><p>返回的字符串是在字符串中用 RE 最左边不重复的匹配来替换。如果模式没有发现，字符将被没有改变地返回。</p><p>可选参数 count 是模式匹配后替换的最大次数；count 必须是非负整数。缺省值是 0 表示替换所有的匹配。</p><p>实例：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python3</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line">phone = <span class="string">&quot;2004-959-559 # 这是一个电话号码&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除注释</span></span><br><span class="line">num = re.sub(<span class="string">r&#x27;#.*$&#x27;</span>, <span class="string">&quot;&quot;</span>, phone)</span><br><span class="line"><span class="built_in">print</span> (<span class="string">&quot;电话号码 : &quot;</span>, num)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 移除非数字的内容</span></span><br><span class="line">num = re.sub(<span class="string">r&#x27;\D&#x27;</span>, <span class="string">&quot;&quot;</span>, phone)</span><br><span class="line"><span class="built_in">print</span> (<span class="string">&quot;电话号码 : &quot;</span>, num)</span><br></pre></td></tr></table></figure><p>以上实例执行结果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">电话号码 :  2004-959-559 </span><br><span class="line">电话号码 :  2004959559</span><br></pre></td></tr></table></figure><p>正则表达式修饰符 - 可选标志<br>正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志：</p><table><thead><tr><th>修饰符</th><th>描述</th></tr></thead><tbody><tr><td>re.I</td><td>使匹配对大小写不敏感</td></tr><tr><td>re.L</td><td>做本地化识别（locale-aware）匹配</td></tr><tr><td>re.M</td><td>多行匹配，影响 ^ 和 $</td></tr><tr><td>re.S</td><td>使 . 匹配包括换行在内的所有字符</td></tr><tr><td>re.U</td><td>根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.</td></tr><tr><td>re.X</td><td>该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。</td></tr></tbody></table><p>正则表达式模式<br>模式字符串使用特殊的语法来表示一个正则表达式：</p><p>字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。</p><p>多数字母和数字前加一个反斜杠时会拥有不同的含义。</p><p>标点符号只有被转义时才匹配自身，否则它们表示特殊的含义。</p><p>反斜杠本身需要使用反斜杠转义。</p><p>由于正则表达式通常都包含反斜杠，所以你最好使用原始字符串来表示它们。模式元素(如 r’/t’，等价于’//t’)匹配相应的特殊字符。</p><p>下面列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数，某些模式元素的含义会改变。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">^   匹配字符串的开头  </span><br><span class="line">$   匹配字符串的末尾。  </span><br><span class="line">.   匹配任意字符，除了换行符，当re.DOTALL标记被指定时，则可以匹配包括换行符的任意字符。  </span><br><span class="line">[...]   用来表示一组字符,单独列出：[amk] 匹配 <span class="string">&#x27;a&#x27;</span>，<span class="string">&#x27;m&#x27;</span>或<span class="string">&#x27;k&#x27;</span>  </span><br><span class="line">[^...]  不在[]中的字符：[^abc] 匹配除了a,b,c之外的字符。  </span><br><span class="line">re* 匹配<span class="number">0</span>个或多个的表达式。  </span><br><span class="line">re+ 匹配<span class="number">1</span>个或多个的表达式。  </span><br><span class="line">re? 匹配0个或1个由前面的正则表达式定义的片段，非贪婪方式  </span><br><span class="line">re&#123; n&#125;  匹配n个前面表达式。例如，<span class="string">&quot;o&#123;2&#125;&quot;</span>不能匹配<span class="string">&quot;Bob&quot;</span>中的<span class="string">&quot;o&quot;</span>，但是能匹配<span class="string">&quot;food&quot;</span>中的两个o。  </span><br><span class="line">re&#123; n,&#125; 精确匹配n个前面表达式。例如，<span class="string">&quot;o&#123;2,&#125;&quot;</span>不能匹配<span class="string">&quot;Bob&quot;</span>中的<span class="string">&quot;o&quot;</span>，但能匹配<span class="string">&quot;foooood&quot;</span>中的所有o。<span class="string">&quot;o&#123;1,&#125;&quot;</span>等价于<span class="string">&quot;o+&quot;</span>。<span class="string">&quot;o&#123;0,&#125;&quot;</span>则等价于<span class="string">&quot;o*&quot;</span>。  </span><br><span class="line">re&#123; n, m&#125;   匹配 n 到 m 次由前面的正则表达式定义的片段，贪婪方式  </span><br><span class="line">a| b    匹配a或b  </span><br><span class="line">(re)    G匹配括号内的表达式，也表示一个组  </span><br><span class="line">(?imx)  正则表达式包含三种可选标志：i, m, 或 x 。只影响括号中的区域。  </span><br><span class="line">(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。  </span><br><span class="line">(?: re) 类似 (...), 但是不表示一个组  </span><br><span class="line">(?imx: re)  在括号中使用i, m, 或 x 可选标志  </span><br><span class="line">(?-imx: re) 在括号中不使用i, m, 或 x 可选标志  </span><br><span class="line">(?#...) 注释.  </span><br><span class="line">(?= re) 前向肯定界定符。如果所含正则表达式，以 ... 表示，在当前位置成功匹配时成功，否则失败。但一旦所含表达式已经尝试，匹配引擎根本没有提高；模式的剩余部分还要尝试界定符的右边。  </span><br><span class="line">(?! re) 前向否定界定符。与肯定界定符相反；当所含表达式不能在字符串当前位置匹配时成功  </span><br><span class="line">(?&gt; re) 匹配的独立模式，省去回溯。  </span><br><span class="line">\w  匹配字母数字  </span><br><span class="line">\W  匹配非字母数字  </span><br><span class="line">\s  匹配任意空白字符，等价于 [\t\n\r\f].  </span><br><span class="line">\S  匹配任意非空字符  </span><br><span class="line">\d  匹配任意数字，等价于 [<span class="number">0</span>-<span class="number">9</span>].  </span><br><span class="line">\D  匹配任意非数字  </span><br><span class="line">\A  匹配字符串开始  </span><br><span class="line">\Z  匹配字符串结束，如果是存在换行，只匹配到换行前的结束字符串。c  </span><br><span class="line">\z  匹配字符串结束   </span><br><span class="line">\G  匹配最后匹配完成的位置。  </span><br><span class="line">\b  匹配一个单词边界，也就是指单词和空格间的位置。例如， <span class="string">&#x27;er\b&#x27;</span> 可以匹配<span class="string">&quot;never&quot;</span> 中的 <span class="string">&#x27;er&#x27;</span>，但不能匹配 <span class="string">&quot;verb&quot;</span> 中的 <span class="string">&#x27;er&#x27;</span>。  </span><br><span class="line">\B  匹配非单词边界。<span class="string">&#x27;er\B&#x27;</span> 能匹配 <span class="string">&quot;verb&quot;</span> 中的 <span class="string">&#x27;er&#x27;</span>，但不能匹配 <span class="string">&quot;never&quot;</span> 中的 <span class="string">&#x27;er&#x27;</span>。  </span><br><span class="line">\n, \t, 等.  匹配一个换行符。匹配一个制表符。等  </span><br><span class="line">\<span class="number">1.</span>..\<span class="number">9</span> 匹配第n个分组的子表达式。  </span><br><span class="line">\<span class="number">10</span> 匹配第n个分组的子表达式，如果它经匹配。否则指的是八进制字符码的表达式。  </span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="正则表达式实例"><a href="#正则表达式实例" class="headerlink" title="正则表达式实例"></a>正则表达式实例</h3><p>字符匹配  </p><table><thead><tr><th>实例</th><th>描述</th></tr></thead><tbody><tr><td>python</td><td>匹配 “python”.</td></tr></tbody></table><p>字符类  </p><table><thead><tr><th>实例</th><th>描述</th></tr></thead><tbody><tr><td>[Pp]ython</td><td>匹配 “Python” 或 “python”</td></tr><tr><td>rub[ye]</td><td>匹配 “ruby” 或 “rube”</td></tr><tr><td>[aeiou]</td><td>匹配中括号内的任意一个字母</td></tr><tr><td>[0-9]</td><td>匹配任何数字。类似于 [0123456789]</td></tr><tr><td>[a-z]</td><td>匹配任何小写字母</td></tr><tr><td>[A-Z]</td><td>匹配任何大写字母</td></tr><tr><td>a-zA-Z0-9]</td><td>匹配任何字母及数字</td></tr><tr><td>[^aeiou] 除了aeiou字母以外的所有字符</td><td></td></tr><tr><td>[^0-9]</td><td>匹配除了数字外的字符</td></tr></tbody></table><p>特殊字符类   </p><table><thead><tr><th>实例</th><th>描述</th></tr></thead><tbody><tr><td>.  匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符，请使用象 ‘[.\n]’ 的模式。</td><td></td></tr><tr><td>\d 匹配一个数字字符。等价于 [0-9]。</td><td></td></tr><tr><td>\D 匹配一个非数字字符。等价于 [^0-9]。</td><td></td></tr><tr><td>\s 匹配任何空白字符，包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。</td><td></td></tr><tr><td>\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。</td><td></td></tr><tr><td>\w 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。</td><td></td></tr><tr><td>\W 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。</td><td></td></tr></tbody></table>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> regex </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>更改Ubuntu默认Python版本方法</title>
      <link href="python/base/python-version-ubuntu/"/>
      <url>python/base/python-version-ubuntu/</url>
      
        <content type="html"><![CDATA[<h3 id="查看首先查看Python3默认版本"><a href="#查看首先查看Python3默认版本" class="headerlink" title="查看首先查看Python3默认版本:"></a>查看首先查看Python3默认版本:</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">victor@victor:/$ python3</span><br><span class="line">Python <span class="number">3.5</span><span class="number">.3</span> (default, Sep <span class="number">27</span> <span class="number">2018</span>, <span class="number">17</span>:<span class="number">25</span>:<span class="number">39</span>) </span><br><span class="line">[GCC <span class="number">6.3</span><span class="number">.0</span> <span class="number">20170516</span>] on linux</span><br><span class="line">Type <span class="string">&quot;help&quot;</span>, <span class="string">&quot;copyright&quot;</span>, <span class="string">&quot;credits&quot;</span> <span class="keyword">or</span> <span class="string">&quot;license&quot;</span> <span class="keyword">for</span> more information.</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span></span><br></pre></td></tr></table></figure><h3 id="搜索系统是否已经安装Python3-7"><a href="#搜索系统是否已经安装Python3-7" class="headerlink" title="搜索系统是否已经安装Python3.7:"></a>搜索系统是否已经安装Python3.7:</h3><p>victor@victor:/$ <code>which python3.7</code><br><code>/usr/local/bin/python3.7</code>  </p><p>这样通过which查看python3.7可执行文件的位置，这个目录后面要用</p><h3 id="在当前用户下修改-Python3-版本："><a href="#在当前用户下修改-Python3-版本：" class="headerlink" title="在当前用户下修改 Python3 版本："></a>在当前用户下修改 Python3 版本：</h3><p>victor@victor:/$ <code>alias python3=&#39;/usr/local/bin/python3.7&#39;</code><br>这里填入刚才查询到的路径  </p><h3 id="一旦完成以上操作，重新登录或者重新加载-bashrc-文件，使操作生效。"><a href="#一旦完成以上操作，重新登录或者重新加载-bashrc-文件，使操作生效。" class="headerlink" title="一旦完成以上操作，重新登录或者重新加载 .bashrc 文件，使操作生效。"></a>一旦完成以上操作，重新登录或者重新加载 .bashrc 文件，使操作生效。</h3><p>victor@victor:/$ <code>. ~/.bashrc</code></p><h3 id="然后就成了，检查一下"><a href="#然后就成了，检查一下" class="headerlink" title="然后就成了，检查一下"></a>然后就成了，检查一下</h3><pre><code>victor@victor:/$ python3Python 3.7.0 (default, Aug 30 2019, 14:02:26) [GCC 6.3.0 20170516] on linuxType &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.&gt;&gt;&gt; </code></pre><p>整体挺好吧</p><h3 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h3><p>博客园：<a href="https://www.cnblogs.com/yifugui/p/8649864.html">Fugui：更改Ubuntu默认python版本的方法</a><br>简  书：<a href="https://www.jianshu.com/p/9d3033d1b26f">给我二两面<br>：更改Ubuntu默认Python版本方法</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> ubuntu </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>ubuntu下安装python3.7</title>
      <link href="python/install/python-install-ubuntu/"/>
      <url>python/install/python-install-ubuntu/</url>
      
        <content type="html"><![CDATA[<h3 id="1">1.准备</h3><p>在安装之前，请使用以下命令安装Python的先决条件。</p><pre data-spm-anchor-id="a2c4e.11153940.0.i2.1e477fd2pcGCTX"><code class="hljs sql" data-spm-anchor-id="a2c4e.11153940.0.i0.1e477fd2pcGCTX">sudo apt-get <span class="hljs-keyword">install</span> <span class="hljs-keyword">build</span>-essential checkinstallsudo apt-<span class="hljs-keyword">get</span> <span class="hljs-keyword">install</span> libreadline-gplv2-dev libncursesw5-dev libssl-dev \    libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev</code></pre><h3 id="2">2.安装</h3><p>使用<a href="https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fwww.python.org%2F" data-url="https://www.python.org/">python</a>官方站点的以下命令下载Python。您也可以下载最新版本代替下面指定的版本。</p><pre><code class="hljs nginx"><span class="hljs-attribute">cd</span> /usr/srcsudo wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz<p>sudo tar xzf Python-<span class="hljs-number">3</span>.<span class="hljs-number">7</span>.<span class="hljs-number">0</span>.tgz<br></code></pre></p><h3 id="3">3. 编译</h3><p>使用下面的命令集来使用altinstall在您的系统上编译python源代码。</p><pre><code class="hljs bash"><span class="hljs-built_in">cd</span> Python-3.7.0sudo ./configure --enable-optimizationssudo make altinstall</code></pre><p>make altinstall用于防止替换默认的python二进制文件/ usr / bin / python。</p><h3 id="4">4.检查Python版本</h3><pre><code class="hljs css"><span class="hljs-selector-tag">python3</span><span class="hljs-selector-class">.7</span> <span class="hljs-selector-tag">-V</span></code></pre><h3 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h3><p>原文链接：<a href="https://yq.aliyun.com/articles/675910">云栖社区-Ubuntu安装python 3.7</a> </p>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
            <tag> ubuntu </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>python安装以及版本检测</title>
      <link href="python/install/python-install-window/"/>
      <url>python/install/python-install-window/</url>
      
        <content type="html"><![CDATA[<h3 id="Windows-安装-Python-3"><a href="#Windows-安装-Python-3" class="headerlink" title="Windows 安装 Python 3"></a>Windows 安装 Python 3</h3><p>目前Python有两个大版本，分别是 2.X 和 3.X ，我们的教程基于最新版本 3.6.1 首先我们需要获取Python的安装包，可以从官网获取，如果你因为没有VPN工具而无法访问官网的话，我已经将它放在网盘了，永久有效。<br>从<a href="https://www.python.org/">Python官网</a> or 从<a href="https://pan.baidu.com/s/1eRYKVFs#list/path=/">网盘获取</a><br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190712201332845.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMjIzOTgz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br>你可以根据电脑的操作系统来选择相应的版本。<br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190712201623738.png" alt="在这里插入图片描述"></p><p>双击安装，请务必将下面的add python 3.6 to path 选中。<br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190712202438373.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMjIzOTgz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br>安装成功后直接关闭即可<br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190712202459225.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMjIzOTgz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br>好了，到这里就已经安装成功啦</p><p>你可以通过 开始 -&gt; 所有程序 -&gt; python 3.6 -&gt; IDLE 打开程序自带的命令行工具<br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/2019071220281150.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMjIzOTgz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br>程序自带的命令行界面<br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190712202847451.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMjIzOTgz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br>或者，你也可以通过 win+R 打开运行窗口， 输入 cmd 回车打开命令行界面，然后输入python命令 回车，也可以进入到python的交互模式中,不过这里面仅仅可以用作测试,不适合大量的代码的编写<br><img src= "/img/loading.gif" data-lazy-src="https://img-blog.csdnimg.cn/20190712202957260.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMjIzOTgz,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><h4 id="如果你还是忘记了勾选添加环境变量的话，请手动配置环境变量"><a href="#如果你还是忘记了勾选添加环境变量的话，请手动配置环境变量" class="headerlink" title="如果你还是忘记了勾选添加环境变量的话，请手动配置环境变量"></a>如果你还是忘记了勾选添加环境变量的话，请手动配置环境变量</h4><p>把安装的Python程序的路径粘贴，复制到<br>我的电脑-&gt;属性-&gt;高级系统设置-&gt;环境变量-&gt;Path选项<br>如果需要，分隔符使用英文的分号(;)即可</p><h2 id="Python版本检测"><a href="#Python版本检测" class="headerlink" title="Python版本检测"></a>Python版本检测</h2><ol><li>在命令行界面输入 python 命令，如果安装成功，则可以进入Python交互界面，第一行即可看到版本信息。</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">DragondeMacBook-Air:~ dragon$ python3</span><br><span class="line">Python 3.6.1 (default, Apr  4 2017, 09:40:21) </span><br><span class="line">[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.38)] on darwin</span><br><span class="line">Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.</span><br><span class="line">&gt;&gt;&gt;</span><br></pre></td></tr></table></figure><ol start="2"><li>在命令行界面输入 python -V即可，无需进入交互界面即可查看版本信息。</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">DragondeMacBook-Air:~ dragon$ python3 -V</span><br><span class="line">Python 3.6.1</span><br></pre></td></tr></table></figure><ol start="3"><li>在Windows的开始菜单，打开Python的IDLE，也可以查看到版本信息。（IDLE是Python软件包自带的一个集成开发环境，初学者可以利用它方便的创建、运行、测试和调试Python程序）</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] on win32</span><br><span class="line">Type &quot;copyright&quot;, &quot;credits&quot; or &quot;license()&quot; for more information.</span><br><span class="line">&gt;&gt;&gt;</span><br></pre></td></tr></table></figure>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> background </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>关于Python3.7和Python3.6中元组类型数据内存存储问题</title>
      <link href="python/base/tuple-type-id/"/>
      <url>python/base/tuple-type-id/</url>
      
        <content type="html"><![CDATA[<h3 id="关于Python3-7和Python3-6中元组类型数据内存存储问题"><a href="#关于Python3-7和Python3-6中元组类型数据内存存储问题" class="headerlink" title="关于Python3.7和Python3.6中元组类型数据内存存储问题"></a>关于Python3.7和Python3.6中元组类型数据内存存储问题</h3><p>小编最近发现了一个瑕疵<br>当定义一个元组类型的变量后,若在程序后面再定义一个元组变量,这两个元组的内容相同,那么在不同的版本中会出现不同的结果<br>在Python3.6版本中,解释器将在内存中开辟两个内存空间分别存储两个元组的内容,也就是说,不管后面定义的元组,每个元组都是单独的互补影响的内存空间,用is方法检测结果为False<br><br></p><h3 id="python3-6版本"><a href="#python3-6版本" class="headerlink" title="python3.6版本"></a>python3.6版本</h3><br><div align="left">    <img src= "/img/loading.gif" data-lazy-src="/img/posts/technology/20190806224625211tuple.png" >  </div>在Python3.7以上版本中,元组将会和数值类型的操作方式类似,若变量内容相同,则只是改变了变量的指向的内存地址,用is方法检测结果为True<br>### python3.7版本<br><div align="left">    <img src= "/img/loading.gif" data-lazy-src="/img/posts/technology/20190806224756626tuple.png" >  </div>### python3.8版本<br><div align="left">    <img src= "/img/loading.gif" data-lazy-src="/img/posts/technology/20190806224651517tuple.png" >  </div>]]></content>
      
      
      
        <tags>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>VSCode设置自动保存</title>
      <link href="comic/vscode-autosave/"/>
      <url>comic/vscode-autosave/</url>
      
        <content type="html"><![CDATA[<p>很多时候敲了一大堆代码，结果手贱或者电脑没电或者电脑突然崩溃，如果没有保存，只能说GG。好在VSCode有自动保存代码的功能，而且有好几种自动保存的模式选择，设置方法如下：</p><p>进入“&gt;文件&gt;首选项&gt;设置”，之后你可以搜索关键字“save”找到如下</p><p><img src= "/img/loading.gif" data-lazy-src="tc4qo0l57.png" alt="image.png"></p><p>可以看到一共有4种选择：</p><ul><li>off：关闭自动保存，这是默认选项</li><li>afterDelay：会每隔若干秒保存一次</li><li>OnFocusChange： 编辑器是去焦点时自动保存文件，比如说你打开了多个文件，你编辑好了A，然后切换到B文件，那么此时A文件会自动保存。</li><li>OnWindowChange：窗口失去焦点时会自动保存文件。也就是说你从VSCode切换到其他软件时会自动保存文件。</li></ul>]]></content>
      
      
      
        <tags>
            
            <tag> ide </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python自动化测试iOS项目</title>
      <link href="python/collection/PythonTestAutomationiOS/"/>
      <url>python/collection/PythonTestAutomationiOS/</url>
      
        <content type="html"><![CDATA[<p>作为一个开发人员，为了保证自己的代码的健壮，写单元测试是必不可少的环节，然而最痛快的是每天去手动跑一遍所有的case。那么什么能帮我们解决这些繁琐的操作呢，大家应该会想到自动化测试脚本了，是的，我们可以借助脚本来完成全自动化测试，下面是我列的每天脚本自动执行流程：       </p><blockquote><ul><li>1、<code>pull</code> git仓库里面的最新代码到本地。    </li><li>2、然后打包成<code>App</code>。   </li><li>3、安装到模拟器上。    </li><li>4、运行App，执行单元测试，生成测试数据并保存到本地。    </li><li>5、脚本读取测试数据，邮件发送给相关人员。    </li></ul></blockquote><p>当这些全自动化后，可以大大减少开发人员的维护成本，即使每次项目里面有新增模块后，增加测试case就行了，下面会介绍自动测试这5步具体怎么去执行，整个脚本是使用Python写的，代码很少功能也很简单，但这已经可以帮我们完成基本的自动化测试了，这就是脚本的强大之处，选择Pyhton纯属个人喜好，最近也在学习Python，当然了最终使用什么语言看你自己。   </p><h3 id="python执行shell命令完成测试"><a href="#python执行shell命令完成测试" class="headerlink" title="python执行shell命令完成测试"></a>python执行shell命令完成测试</h3><p>首先确认本机上安装了<code>git</code> 和 <code>python</code> 。<br>脚本判断本地是否存在项目，不存在则使用命令 <code>git clone ...</code> ，存在则使用命令 <code>git pull ...</code> 。<br>这些在Linux的命令都可以使用脚本来完成的，python的 <code>os.popen()</code> 方法 就是可以在Linux上执行shell命令。<br><strong>例如：</strong>  把下面这段代码添加到一个 test.py 的文件里，然后在终端上执行 <code>python test.py</code> 命令你就会看到，你的当前目录下正在下载我的博客了。</p><pre><code>import osos.popen(&#39;git clone https://github.com/leopardpan/leopardpan.github.io.git&#39;)   </code></pre><p>git pull 。。。 更新代码也是一样的。</p><p>接下来的打包、安装、运行都是使用python执行shell命令      </p><p><strong>把iOS项目打包成App，下面的 <code>Demo</code> 是项目的名字</strong>              </p><blockquote><ul><li>os.popen(‘xcodebuild -project Demo.xcodeproj -target Demo -configuration Debug -sdk iphonesimulator’)     </li></ul></blockquote><p>这行脚本运行完成后，你就会发现同会生成一个 <code>build</code> 的文件夹。<br>Debug参数表示现在是Debug模式，如果Xcode里面改成Release了，这里需要改成Release。<br>xcodebuild 命令是 Xcode Command Line Tools 的一部分。通过调用这个命令，可以完成 iOS 工程的编译，打包和签名过程。可以使用 xcodebuild –help 来看看具体有哪些功能。 </p><p><strong>打开iOS模拟器，这里运行的是<code>iPhone 6 Plus</code> 你也可以换成其它型号的模拟器</strong>      </p><blockquote><ul><li> os.popen(‘xcrun instruments -w “iPhone 6 Plus”‘)    </li></ul></blockquote><p><strong>把刚才打包生成的App安装到模拟器上</strong><br>在安装之前要先卸载App,不然你运行的永远是最初安装的那个，后来安装的不会覆盖之前的，卸载App</p><blockquote><ul><li>os.popen(‘xcrun simctl uninstall booted com.test.Demo’)</li></ul></blockquote><p>booted 后面接的是 <code>Bundle Identifier</code>，我的是 com.test.Demo，然后再安装App     </p><blockquote><ul><li>os.popen(‘xcrun simctl install booted build/Debug-iphonesimulator/Demo.app ‘)    </li></ul></blockquote><p>booted 后面接的是.app的路径，我打包的时候的是Debug，所以这个的文件夹名称是Debug-iphonesimulator。</p><p><strong>在模拟器里运行App</strong>      </p><blockquote><ul><li>os.popen(‘xcrun simctl launch booted com.test.Demo’)</li></ul></blockquote><p>booted 后面接的是 <code>Bundle Identifier</code>，我的是 com.test.Demo。</p><p>到目前为止，你就会发现你的项目已经运行起来了，你可以在项目是Debug模式下一启动就执行单元测试，然后把对应的测试数据保存到本地为data.json。然后在使用python脚本读取测试文件的数据，最终使用邮件发送给相关人员，pyhton读取数据很简单，一行代码就行</p><blockquote><ul><li>data = open(‘data.json’).read() </li></ul></blockquote><p>data里面就是json字符串，为了脚本操作简单，我在存储的时候直接把json格式的转成了字符串类型。</p><h3 id="python发送邮件"><a href="#python发送邮件" class="headerlink" title="python发送邮件"></a>python发送邮件</h3><p>我使用的是SMTP进行邮件发送的，SMTP是发送邮件的协议，Python内置对SMTP的支持，可以发送纯文本邮件、HTML邮件以及带附件的邮件。     </p><p>Python对SMTP支持有smtplib和email两个模块，email负责构造邮件，smtplib负责发送邮件，具体代码如下： </p><pre><code>from email import encodersfrom email.header import Headerfrom email.mime.text import MIMETextfrom email.utils import parseaddr, formataddrimport smtplibdef format_addr(self,s):    name, addr = parseaddr(s)    return formataddr(( \        Header(name, &#39;utf-8&#39;).encode(), \        addr.encode(&#39;utf-8&#39;) if isinstance(addr, unicode) else addr))def send_mail(self, mail, message, title):    from_addr = &#39;leopardpan@163.com&#39;    password = &#39;&#39;    to_addr = mail    smtp_server = &#39;smtp.163.com&#39;    msg = MIMEText(message, &#39;plain&#39;, &#39;utf-8&#39;)    msg[&#39;From&#39;] = self.format_addr(u&#39;自动化测试邮件 &lt;%s&gt;&#39; % from_addr)    msg[&#39;To&#39;] = self.format_addr(u&#39;管理员 &lt;%s&gt;&#39; % to_addr)    msg[&#39;Subject&#39;] = Header(title, &#39;utf-8&#39;).encode()    server = smtplib.SMTP(smtp_server, 25)    server.set_debuglevel(1)    server.login(from_addr, password)    server.sendmail(from_addr, [to_addr], msg.as_string())    server.quit()send_mail(&#39;leopardpan@icloud.com&#39;,&#39;正文&#39;,&#39;标题&#39;)</code></pre><p>from_addr是发送方的邮箱地址，password是开通SMTP时输入的密码<br>smtp_server是smtp的服务，如果你的from_addr是gamil.com，那么就要写成smtp_server = ‘smtp.gmail.com’ 了。</p><p>方法 send_mail(self, mail, message, title): 有四个参数，第一个不用传，第二个参数是收信人的邮箱，第三个是邮件的正文，第四个是邮件的标题，方法调用格式： <code>send_mail(&#39;leopardpan@icloud.com&#39;,&#39;正文&#39;,&#39;标题&#39;)</code></p><p>注意：发送方的邮箱必须要开通SMTP功能才行，否则会报错</p><blockquote><ul><li>SMTPSenderRefused: (550, ‘User has no permission’, ‘leopardpan@163.com’)</li></ul></blockquote><p>163的SMTP开通，需要你登录网易邮箱，然后点击顶部的设置就会出现<code>POP3/SMTP/IMAP</code>，点击之后，勾选选择开启，这个时候需要你输入密码，记住这个密码就是上面代码中的<code>password</code>，如果你都完成的话，你把上面的代码拷贝出现，把邮箱修改成你自己的，使用 pyhton 运行一下吧。</p><p>上面的几个流程结合起来就可以实现一个简单的自动化测试了，如果你有什么建议和意见欢迎讨论。</p><p>参考链接：<br><a href="http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832745198026a685614e7462fb57dbf733cc9f3ad000">SMTP发送邮件</a>     </p><br><p>转载请注明：<a href="http://baixin/">潘柏信的博客</a> » <a href="http://baixin.io/2016/08/PythonTestAutomationiOS/">点击阅读原文</a> </p>]]></content>
      
      
      
        <tags>
            
            <tag> python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>从头到尾彻底理解KMP</title>
      <link href="unclass/algorithm-tmp/"/>
      <url>unclass/algorithm-tmp/</url>
      
        <content type="html"><![CDATA[<p>作者：July<br>时间：最初写于2011年12月，2014年7月21日晚10点 全部删除重写成此文，随后的半个多月不断反复改进。后收录于新书《<a href="http://item.jd.com/11786791.html">编程之法：面试和算法心得</a>》第4.4节中。</p><h2 id="1-引言"><a href="#1-引言" class="headerlink" title="1. 引言"></a>1. 引言</h2><p>  本KMP原文最初写于2年多前的2011年12月，因当时初次接触KMP，思路混乱导致写也写得混乱。所以一直想找机会重新写下KMP，但苦于一直以来对KMP的理解始终不够，故才迟迟没有修改本文。</p><p>  KMP本身不复杂，但网上绝大部分的文章（包括本文的2011年版本）把它讲混乱了。下面，咱们从暴力匹配算法讲起，随后阐述KMP的流程 步骤、next 数组的简单求解 递推原理 代码求解，接着基于next 数组匹配，谈到有限状态自动机，next 数组的优化，KMP的时间复杂度分析，最后简要介绍两个KMP的扩展算法。</p><p>  全文力图给你一个最为完整最为清晰的KMP，希望更多的人不再被KMP折磨或纠缠，不再被一些混乱的文章所混乱。有何疑问，欢迎随时留言评论，thanks。</p><h2 id="2-暴力匹配算法"><a href="#2-暴力匹配算法" class="headerlink" title="2. 暴力匹配算法"></a>2. 暴力匹配算法</h2><p>  假设现在我们面临这样一个问题：有一个文本串S，和一个模式串P，现在要查找P在S中的位置，怎么查找呢？</p><p>  如果用暴力匹配的思路，并假设现在文本串S匹配到 i 位置，模式串P匹配到 j 位置，则有：</p><ul><li><p>如果当前字符匹配成功（即S[i] == P[j]），则i++，j++，继续匹配下一个字符；</p></li><li><p>如果失配（即S[i]! = P[j]），令i = i - (j - 1)，j = 0。相当于每次匹配失败时，i 回溯，j 被置为0。</p><p>理清楚了暴力匹配算法的流程及内在的逻辑，咱们可以写出暴力匹配的代码，如下：</p></li></ul><p>**<br>**</p><ol><li>int ViolentMatch(char* s, char* p) </li><li>{ </li><li>  int sLen = strlen(s); </li><li>  int pLen = strlen(p); </li><li></li><li>  int i = 0; </li><li>  int j = 0; </li><li>  <strong>while (i &lt; sLen &amp;&amp; j &lt; pLen)</strong> </li><li>  { </li><li>​    <strong>if (s[i] == p[j])</strong> </li><li>​    { </li><li>​      //①如果当前字符匹配成功（即S[i] == P[j]），则i++，j++   </li><li>​      i++; </li><li>​      j++; </li><li>​    } </li><li>​    <strong>else</strong> </li><li>​    { </li><li>​      //②如果失配（即S[i]! = P[j]），令i = i - (j - 1)，j = 0   </li><li>​      i = i - j + 1; </li><li>​      j = 0; </li><li>​    } </li><li>  } </li><li>  //匹配成功，返回模式串p在文本串s中的位置，否则返回-1 </li><li>  <strong>if (j == pLen)</strong> </li><li>​    <strong>return i - j;</strong> </li><li>  <strong>else</strong> </li><li>​    <strong>return -1;</strong> </li><li>} </li></ol><p>  举个例子，如果给定文本串S“BBC ABCDAB ABCDABCDABDE”，和模式串P“ABCDABD”，现在要拿模式串P去跟文本串S匹配，整个过程如下所示：</p><p>  <em>1.</em> S[0]为B，P[0]为A，不匹配，执行第②条指令：“如果失配（即S[i]! = P[j]），令i = i - (j - 1)，j = 0”，S[1]跟P[0]匹配，相当于模式串要往右移动一位（i=1，j=0）</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140723224710203" alt="img"></p></blockquote><p>  <em>2</em>. S[1]跟P[0]还是不匹配，继续执行第②条指令：“如果失配（即S[i]! = P[j]），令i = i - (j - 1)，j = 0”，S[2]跟P[0]匹配（i=2，j=0），从而模式串不断的向右移动一位（不断的执行“令i = i - (j - 1)，j = 0”，i从2变到4，j一直为0）</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140726213551553" alt="img"></p></blockquote><p>  <em>3</em>. 直到S[4]跟P[0]匹配成功（i=4，j=0），此时按照上面的暴力匹配算法的思路，转而执行第①条指令：“如果当前字符匹配成功（即S[i] == P[j]），则i++，j++”，可得S[i]为S[5]，P[j]为P[1]，即接下来S[5]跟P[1]匹配（i=5，j=1）</p><blockquote><p>   <img src= "/img/loading.gif" data-lazy-src="20140726213602848" alt="img"></p></blockquote><p>  <em>4</em>. S[5]跟P[1]匹配成功，继续执行第①条指令：“如果当前字符匹配成功（即S[i] == P[j]），则i++，j++”，得到S[6]跟P[2]匹配（i=6，j=2），如此进行下去</p><blockquote><p>  <img src= "/img/loading.gif" data-lazy-src="20140726213343578" alt="img"></p></blockquote><p>  <em>5</em>. 直到S[10]为空格字符，P[6]为字符D（i=10，j=6），因为不匹配，重新执行第②条指令：“如果失配（即S[i]! = P[j]），令i = i - (j - 1)，j = 0”，相当于S[5]跟P[0]匹配（i=5，j=0）</p><blockquote><p>   <img src= "/img/loading.gif" data-lazy-src="20140726213353687" alt="img"></p></blockquote><p>  <em>6</em>. 至此，我们可以看到，如果按照暴力匹配算法的思路，尽管之前文本串和模式串已经分别匹配到了S[9]、P[5]，但因为S[10]跟P[6]不匹配，所以文本串回溯到S[5]，模式串回溯到P[0]，从而让S[5]跟P[0]匹配。</p><p><img src= "/img/loading.gif" data-lazy-src="20140726213631208" alt="img"></p><p>  而S[5]肯定跟P[0]失配。为什么呢？因为在之前第4步匹配中，我们已经得知S[5] = P[1] = B，而P[0] = A，即P[1] != P[0]，故S[5]必定不等于P[0]，所以回溯过去必然会导致失配。那有没有一种算法，让i 不往回退，只需要移动j 即可呢？</p><p>  答案是肯定的。这种算法就是本文的主旨KMP算法，它利用之前已经部分匹配这个有效信息，保持i 不回溯，通过修改j 的位置，让模式串尽量地移动到有效的位置。</p><h2 id="3-KMP算法"><a href="#3-KMP算法" class="headerlink" title="3. KMP算法"></a>3. KMP算法</h2><h3 id="3-1-定义"><a href="#3-1-定义" class="headerlink" title="3.1 定义"></a>3.1 定义</h3><p>  Knuth-Morris-Pratt 字符串查找算法，简称为 “KMP算法”，常用于在一个文本串S内查找一个模式串P 的出现位置，这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表，故取这3人的姓氏命名此算法。</p><p>  下面先直接给出KMP的算法流程（如果感到一点点不适，没关系，坚持下，稍后会有具体步骤及解释，越往后看越会柳暗花明☺）：</p><ul><li><p>假设现在文本串S匹配到 i 位置，模式串P匹配到 j 位置</p><ul><li>如果j = -1，或者当前字符匹配成功（即S[i] == P[j]），都令i++，j++，继续匹配下一个字符；</li><li>如果j != -1，且当前字符匹配失败（即S[i] != P[j]），则令 i 不变，j = next[j]。此举意味着失配时，模式串P相对于文本串S向右移动了j - next [j] 位。<ul><li>换言之，当匹配失败时，模式串向右移动的位数为：失配字符所在位置 - 失配字符对应的next 值（next 数组的求解会在下文的<a href="http://blog.csdn.net/v_july_v/article/details/7041827#t9">3.3.3节</a>中详细阐述），即移动的实际位数为：j - next[j]，且此值大于等于1。</li></ul></li></ul><p>很快，你也会意识到next 数组各值的含义：代表当前字符之前的字符串中，有多大长度的相同前缀后缀。例如如果next [j] = k，代表j 之前的字符串中有最大长度为<em>k</em> 的相同前缀后缀。</p><p>此也意味着在某个字符失配时，该字符对应的next 值会告诉你下一步匹配中，模式串应该跳到哪个位置（跳到next [j] 的位置）。如果next [j] 等于0或-1，则跳到模式串的开头字符，若next [j] = k 且 k &gt; 0，代表下次匹配跳到j 之前的某个字符，而不是跳到开头，且具体跳过了k 个字符。</p><p>转换成代码表示，则是：</p></li></ul><p>**<br>**</p><ol><li>int KmpSearch(char* s, char* p) </li><li>{ </li><li>  int i = 0; </li><li>  int j = 0; </li><li>  int sLen = strlen(s); </li><li>  int pLen = strlen(p); </li><li>  <strong>while (i &lt; sLen &amp;&amp; j &lt; pLen)</strong> </li><li>  { </li><li>​    //①如果j = -1，或者当前字符匹配成功（即S[i] == P[j]），都令i++，j++   </li><li>​    <strong>if (j == -1 || s[i] == p[j])</strong> </li><li>​    { </li><li>​      i++; </li><li>​      j++; </li><li>​    } </li><li>​    <strong>else</strong> </li><li>​    { </li><li>​      //②如果j != -1，且当前字符匹配失败（即S[i] != P[j]），则令 i 不变，j = next[j]   </li><li>​      //next[j]即为j所对应的next值    </li><li>​      j = next[j]; </li><li>​    } </li><li>  } </li><li>  <strong>if (j == pLen)</strong> </li><li>​    <strong>return i - j;</strong> </li><li>  <strong>else</strong> </li><li>​    <strong>return -1;</strong> </li><li>} </li></ol><p>  继续拿之前的例子来说，当S[10]跟P[6]匹配失败时，KMP不是跟暴力匹配那样简单的把模式串右移一位，而是执行第②条指令：“如果j != -1，且当前字符匹配失败（即S[i] != P[j]），则令 i 不变，j = next[j]”，即j 从6变到2（后面我们将求得P[6]，即字符D对应的next 值为2），所以相当于模式串向右移动的位数为j - next[j]（j - next[j] = 6-2 = 4）。</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140726213353687" alt="img"></p></blockquote><p>  向右移动4位后，S[10]跟P[2]继续匹配。为什么要向右移动4位呢，因为移动4位后，模式串中又有个“AB”可以继续跟S[8]S[9]对应着，从而不用让i 回溯。相当于在除去字符D的模式串子串中寻找相同的前缀和后缀，然后根据前缀后缀求出next 数组，最后基于next 数组进行匹配（不关心next 数组是怎么求来的，只想看匹配过程是咋样的，可直接跳到下文<a href="http://blog.csdn.net/v_july_v/article/details/7041827#t10">3.3.4节</a>）。</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223539765" alt="img"></p></blockquote><h3 id="3-2-步骤"><a href="#3-2-步骤" class="headerlink" title="3.2 步骤"></a>3.2 步骤</h3><ul><li>①寻找前缀后缀最长公共元素长度<ul><li>对于P = p0 p1 …pj-1 pj，寻找模式串P中长度最大且相等的前缀和后缀。如果存在p0 p1 …pk-1 pk = pj- k pj-k+1…pj-1 pj，那么在包含pj的模式串中有最大长度为k+1的相同前缀后缀。举个例子，如果给定的模式串为“abab”，那么它的各个子串的前缀后缀的公共元素的最大长度如下表格所示：</li></ul></li></ul><blockquote><p>比如对于字符串aba来说，它有长度为1的相同前缀后缀a；而对于字符串abab来说，它有长度为2的相同前缀后缀ab（相同前缀后缀的长度为k + 1，k + 1 = 2）。</p></blockquote><ul><li>②求next数组<ul><li>next 数组考虑的是除当前字符外的最长相同前缀后缀，所以通过第①步骤求得各个前缀后缀的公共元素的最大长度后，只要稍作变形即可：将第①步骤中求得的值整体右移一位，然后初值赋为-1，如下表格所示：</li></ul></li></ul><blockquote><p>比如对于aba来说，第3个字符a之前的字符串ab中有长度为0的相同前缀后缀，所以第3个字符a对应的next值为0；而对于abab来说，第4个字符b之前的字符串aba中有长度为1的相同前缀后缀a，所以第4个字符b对应的next值为1（相同前缀后缀的长度为k，k = 1）。</p></blockquote><ul><li>③根据next数组进行匹配<ul><li>匹配失配，j = next [j]，模式串向右移动的位数为：j - next[j]。换言之，当模式串的后缀pj-k pj-k+1, …, pj-1 跟文本串si-k si-k+1, …, si-1匹配成功，但pj 跟si匹配失败时，因为next[j] = k，相当于在不包含pj的模式串中有最大长度为k 的相同前缀后缀，即p0 p1 …pk-1 = pj-k pj-k+1…pj-1，故令j = next[j]，从而让模式串右移j - next[j] 位，使得模式串的前缀p0 p1, …, pk-1对应着文本串 si-k si-k+1, …, si-1，而后让pk 跟si 继续匹配。如下图所示：</li></ul></li></ul><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140812223633281" alt="img"></p></blockquote></blockquote><p>  综上，KMP的next 数组相当于告诉我们：当模式串中的某个字符跟文本串中的某个字符匹配失配时，模式串下一步应该跳到哪个位置。如模式串中在j 处的字符跟文本串在i 处的字符匹配失配时，下一步用next [j] 处的字符继续跟文本串i 处的字符匹配，相当于模式串向右移动 j - next[j] 位。</p><p>  接下来，分别具体解释上述3个步骤。</p><h3 id="3-3-解释"><a href="#3-3-解释" class="headerlink" title="3.3 解释"></a>3.3 解释</h3><h4 id="3-3-1-寻找最长前缀后缀"><a href="#3-3-1-寻找最长前缀后缀" class="headerlink" title="3.3.1 寻找最长前缀后缀"></a>3.3.1 寻找最长前缀后缀</h4><p>  如果给定的模式串是：“ABCDABD”，从左至右遍历整个模式串，其各个子串的前缀后缀分别如下表格所示：<img src= "/img/loading.gif" data-lazy-src="20140725231726921" alt="img"></p><p>  也就是说，原模式串子串对应的各个前缀后缀的公共元素的最大长度表为（下简称《最大长度表》）：</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721222801918" alt="img"></p></blockquote><h4 id="3-3-2-基于《最大长度表》匹配"><a href="#3-3-2-基于《最大长度表》匹配" class="headerlink" title="3.3.2 基于《最大长度表》匹配"></a>3.3.2 基于《最大长度表》匹配</h4><p>  因为模式串中首尾可能会有重复的字符，故可得出下述结论：</p><blockquote><p>失配时，模式串向右移动的位数为：已匹配字符数 - 失配字符的上一位字符所对应的最大长度值</p></blockquote><p>  下面，咱们就结合之前的《最大长度表》和上述结论，进行字符串的匹配。如果给定文本串“BBC ABCDAB ABCDABCDABDE”，和模式串“ABCDABD”，现在要拿模式串去跟文本串匹配，如下图所示：</p><blockquote><p>​    <img src= "/img/loading.gif" data-lazy-src="20140723224710203" alt="img"></p></blockquote><ul><li>\1. 因为模式串中的字符A跟文本串中的字符B、B、C、空格一开始就不匹配，所以不必考虑结论，直接将模式串不断的右移一位即可，直到模式串中的字符A跟文本串的第5个字符A匹配成功：</li></ul><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140726213602848" alt="img"></p></blockquote></blockquote><ul><li><em>2</em>. 继续往后匹配，当模式串最后一个字符D跟文本串匹配时失配，显而易见，模式串需要向右移动。但向右移动多少位呢？因为此时已经匹配的字符数为6个（ABCDAB），然后根据《最大长度表》可得失配字符D的上一位字符B对应的长度值为2，所以根据之前的结论，可知需要向右移动6 - 2 = 4 位。</li></ul><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223809617" alt="img"></p></blockquote></blockquote><ul><li><em>3</em>. 模式串向右移动4位后，发现C处再度失配，因为此时已经匹配了2个字符（AB），且上一位字符B对应的最大长度值为0，所以向右移动：2 - 0 =2 位。</li></ul><blockquote><p>​      <img src= "/img/loading.gif" data-lazy-src="20140721223539765" alt="img"></p></blockquote><ul><li><em>4</em>. A与空格失配，向右移动1 位。</li></ul><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223823548" alt="img"></p></blockquote></blockquote><ul><li><em>5</em>. 继续比较，发现D与C 失配，故向右移动的位数为：已匹配的字符数6减去上一位字符B对应的最大长度2，即向右移动6 - 2 = 4 位。</li></ul><blockquote><p>​      <img src= "/img/loading.gif" data-lazy-src="20140721223558140" alt="img"></p></blockquote><ul><li><em>6</em>. 经历第5步后，发现匹配成功，过程结束。</li></ul><blockquote><p>​     <img src= "/img/loading.gif" data-lazy-src="20140721223611515" alt="img"></p></blockquote><p>  通过上述匹配过程可以看出，问题的关键就是寻找模式串中最大长度的相同前缀和后缀，找到了模式串中每个字符之前的前缀和后缀公共部分的最大长度后，便可基于此匹配。而这个最大长度便正是next 数组要表达的含义。</p><h4 id="3-3-3-根据《最大长度表》求next-数组"><a href="#3-3-3-根据《最大长度表》求next-数组" class="headerlink" title="3.3.3 根据《最大长度表》求next 数组"></a>3.3.3 根据《最大长度表》求next 数组</h4><p>  由上文，我们已经知道，字符串“ABCDABD”各个前缀后缀的最大公共元素长度分别为：</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721230517324" alt="img"></p></blockquote><p>  而且，根据这个表可以得出下述结论</p><ul><li><p>失配时，模式串向右移动的位数为：已匹配字符数 - 失配字符的上一位字符所对应的最大长度值</p><p>上文利用这个表和结论进行匹配时，我们发现，当匹配到一个字符失配时，其实没必要考虑当前失配的字符，更何况我们每次失配时，都是看的失配字符的上一位字符对应的最大长度值。如此，便引出了next 数组。</p><p>给定字符串“ABCDABD”，可求得它的next 数组如下：</p></li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721230250468" alt="img"></p></blockquote><p>  把next 数组跟之前求得的最大长度表对比后，不难发现，next 数组相当于“最大长度值” 整体向右移动一位，然后初始值赋为-1。意识到了这一点，你会惊呼原来next 数组的求解竟然如此简单：就是找最大对称长度的前缀后缀，然后整体右移一位，初值赋为-1（当然，你也可以直接计算某个字符对应的next值，就是看这个字符之前的字符串中有多大长度的相同前缀后缀）。</p><p>  换言之，对于给定的模式串：ABCDABD，它的最大长度表及next 数组分别如下：</p><p><img src= "/img/loading.gif" data-lazy-src="20140728110939595" alt="img"></p><p>  根据最大长度表求出了next 数组后，从而有</p><blockquote><p>失配时，模式串向右移动的位数为：失配字符所在位置 - 失配字符对应的next 值</p></blockquote><p>  而后，你会发现，无论是基于《最大长度表》的匹配，还是基于next 数组的匹配，两者得出来的向右移动的位数是一样的。为什么呢？因为：</p><ul><li><p>根据《最大长度表》，失配时，模式串向右移动的位数 = 已经匹配的字符数 - 失配字符的上一位字符的最大长度值</p></li><li><p>而根据《next 数组》，失配时，模式串向右移动的位数 = 失配字符的位置 - 失配字符对应的next 值</p><ul><li>其中，从0开始计数时，失配字符的位置 = 已经匹配的字符数（失配字符不计数），而失配字符对应的next 值 = 失配字符的上一位字符的最大长度值，两相比较，结果必然完全一致。</li></ul><p>所以，你可以把《最大长度表》看做是next 数组的雏形，甚至就把它当做next 数组也是可以的，区别不过是怎么用的问题。</p></li></ul><h4 id="3-3-4-通过代码递推计算next-数组"><a href="#3-3-4-通过代码递推计算next-数组" class="headerlink" title="3.3.4 通过代码递推计算next 数组"></a>3.3.4 通过代码递推计算next 数组</h4><p>  接下来，咱们来写代码求下next 数组。</p><p>  基于之前的理解，可知计算next 数组的方法可以采用递推：</p><ul><li><p>1</p><p>. 如果对于值k，已有p0 p1, …, pk-1 = pj-k pj-k+1, …, pj-1，相当于next[j] = k。</p><ul><li>此意味着什么呢？究其本质，next[j] = k 代表p[j] 之前的模式串子串中，有长度为k 的相同前缀和后缀。有了这个next 数组，在KMP匹配中，当模式串中j 处的字符失配时，下一步用next[j]处的字符继续跟文本串匹配，相当于模式串向右移动j - next[j] 位。</li></ul></li></ul><blockquote><blockquote><p>举个例子，如下图，根据模式串“ABCDABD”的next 数组可知失配位置的字符D对应的next 值为2，代表字符D前有长度为2的相同前缀和后缀（这个相同的前缀后缀即为“AB”），失配后，模式串需要向右移动j - next [j] = 6 - 2 =4位。</p><p>向右移动4位后，模式串中的字符C继续跟文本串匹配。</p></blockquote></blockquote><blockquote><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223539765" alt="img"></p></blockquote></blockquote></blockquote><ul><li><p>\2. 下面的问题是：已知next [0, …, j]，如何求出next [j + 1]呢？</p><p>对于P的前j+1个序列字符：</p></li><li><p>若p[k] == p[j]，则next[j + 1 ] = next [j] + 1 = k + 1；</p></li><li><p>若p[k ] ≠ p[j]，如果此时p[ next[k] ] == p[j ]，则next[ j + 1 ] =  next[k] + 1，否则继续递归前缀索引k = next[k]，而后重复此过程。 相当于在字符p[j+1]之前不存在长度为k+1的前缀”p0 p1, …, pk-1 pk”跟后缀“pj-k pj-k+1, …, pj-1 pj”相等，那么是否可能存在另一个值t+1 &lt; k+1，使得长度更小的前缀 “p0 p1, …, pt-1 pt” 等于长度更小的后缀 “pj-t pj-t+1, …, pj-1 pj” 呢？如果存在，那么这个t+1 便是next[ j+1]的值，此相当于利用已经求得的next 数组（next [0, …, k, …, j]）进行P串前缀跟P串后缀的匹配。</p><p>一般的文章或教材可能就此一笔带过，但大部分的初学者可能还是不能很好的理解上述求解next 数组的原理，故接下来，我再来着重说明下。</p><p>如下图所示，假定给定模式串ABCDABCE，且已知next [j] = k（相当于“p0 pk-1” = “pj-k pj-1” = AB，可以看出k为2），现要求next [j + 1]等于多少？因为pk = pj = C，所以next[j + 1] = next[j] + 1 = k + 1（可以看出next[j + 1] = 3）。代表字符E前的模式串中，有长度k+1 的相同前缀后缀。</p></li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140729182154066" alt="img"></p></blockquote><p>  但如果pk != pj 呢？说明“p0 pk-1 pk”  ≠ “pj-k pj-1 pj”。换言之，当pk != pj后，字符E前有多大长度的相同前缀后缀呢？很明显，因为C不同于D，所以ABC 跟 ABD不相同，即字符E前的模式串没有长度为k+1的相同前缀后缀，也就不能再简单的令：next[j + 1] = next[j] + 1 。所以，咱们只能去寻找长度更短一点的相同前缀后缀。</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140729181940812" alt="img"></p></blockquote><p>  结合上图来讲，若能在前缀“ p0 pk-1 pk ” 中不断的递归前缀索引k = next [k]，找到一个字符pk’ 也为D，代表pk’ = pj，且满足p0 pk’-1 pk’ = pj-k’ pj-1 pj，则最大相同的前缀后缀长度为k’ + 1，从而next [j + 1] = k’ + 1 = next [k’ ] + 1。否则前缀中没有D，则代表没有相同的前缀后缀，next [j + 1] = 0。</p><p>  那为何递归前缀索引k = next[k]，就能找到长度更短的相同前缀后缀呢？这又归根到next数组的含义。我们拿前缀 p0 pk-1 pk 去跟后缀pj-k pj-1 pj匹配，如果pk 跟pj 失配，下一步就是用p[next[k]] 去跟pj 继续匹配，如果p[ next[k] ]跟pj还是不匹配，则需要寻找长度更短的相同前缀后缀，即下一步用p[ next[ next[k] ] ]去跟pj匹配。此过程相当于模式串的自我匹配，所以不断的递归k = next[k]，直到要么找到长度更短的相同前缀后缀，要么没有长度更短的相同前缀后缀。如下图所示：</p><p>  <img src= "/img/loading.gif" data-lazy-src="20150812214857858" alt="img"></p><p>  所以，因最终在前缀ABC中没有找到D，故E的next 值为0：</p><blockquote><blockquote><p>模式串的后缀：ABDE</p></blockquote></blockquote><blockquote><blockquote><p>模式串的前缀：ABC</p></blockquote></blockquote><blockquote><blockquote><p>前缀右移两位：   ABC</p></blockquote></blockquote><p>  读到此，有的读者可能又有疑问了，那能否举一个能在前缀中找到字符D的例子呢？OK，咱们便来看一个能在前缀中找到字符D的例子，如下图所示：</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140809163257703" alt="img"></p></blockquote><p>  给定模式串DABCDABDE，我们很顺利的求得字符D之前的“DABCDAB”的各个子串的最长相同前缀后缀的长度分别为0 0 0 0 1 2 3，但当遍历到字符D，要求包括D在内的“DABCDABD”最长相同前缀后缀时，我们发现pj处的字符D跟pk处的字符C不一样，换言之，前缀DABC的最后一个字符C 跟后缀DABD的最后一个字符D不相同，所以不存在长度为4的相同前缀后缀。</p><p>  怎么办呢？既然没有长度为4的相同前缀后缀，咱们可以寻找长度短点的相同前缀后缀，最终，因在p0处发现也有个字符D，p0 = pj，所以p[j]对应的长度值为1，相当于E对应的next 值为1（即字符E之前的字符串“DABCDABD”中有长度为1的相同前缀和后缀）。</p><p>  综上，可以通过递推求得next 数组，代码如下所示：</p><ol><li><strong>void GetNext(char* p,int next[])</strong> </li><li>{ </li><li>  int pLen = strlen(p); </li><li>  next[0] = -1; </li><li>  int k = -1; </li><li>  int j = 0; </li><li>  <strong>while (j &lt; pLen - 1)</strong> </li><li>  { </li><li>​    //p[k]表示前缀，p[j]表示后缀 </li><li>​    <strong>if (k == -1 || p[j] == p[k])</strong>  </li><li>​    { </li><li>​      ++k; </li><li>​      ++j; </li><li>​      next[j] = k; </li><li>​    } </li><li>​    <strong>else</strong>  </li><li>​    { </li><li>​      k = next[k]; </li><li>​    } </li><li>  } </li><li>} </li></ol><p>  用代码重新计算下“ABCDABD”的next 数组，以验证之前通过“最长相同前缀后缀长度值右移一位，然后初值赋为-1”得到的next 数组是否正确，计算结果如下表格所示：</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140812004705968" alt="img"></p></blockquote><p>  从上述表格可以看出，无论是之前通过“最长相同前缀后缀长度值右移一位，然后初值赋为-1”得到的next 数组，还是之后通过代码递推计算求得的next 数组，结果是完全一致的。</p><h4 id="3-3-5-基于《next-数组》匹配"><a href="#3-3-5-基于《next-数组》匹配" class="headerlink" title="3.3.5 基于《next 数组》匹配"></a>3.3.5 基于《next 数组》匹配</h4><p>  下面，我们来基于next 数组进行匹配。</p><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721231622000" alt="img"></p></blockquote></blockquote><p>  还是给定文本串“BBC ABCDAB ABCDABCDABDE”，和模式串“ABCDABD”，现在要拿模式串去跟文本串匹配，如下图所示：</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140723224710203" alt="img"></p></blockquote><p>  在正式匹配之前，让我们来再次回顾下上文2.1节所述的KMP算法的匹配流程：</p><ul><li><p>“假设现在文本串S匹配到 i 位置，模式串P匹配到 j 位置</p><ul><li>如果j = -1，或者当前字符匹配成功（即S[i] == P[j]），都令i++，j++，继续匹配下一个字符；</li><li>如果j != -1，且当前字符匹配失败（即S[i] != P[j]），则令 i 不变，j = next[j]。此举意味着失配时，模式串P相对于文本串S向右移动了j - next [j] 位。<ul><li>换言之，当匹配失败时，模式串向右移动的位数为：失配字符所在位置 - 失配字符对应的next 值，即移动的实际位数为：j - next[j]，且此值大于等于1。”</li></ul></li></ul></li><li><p>1</p><p>. 最开始匹配时</p><ul><li>P[0]跟S[0]匹配失败<ul><li>所以执行“如果j != -1，且当前字符匹配失败（即S[i] != P[j]），则令 i 不变，j = next[j]”，所以j = -1，故转而执行“如果j = -1，或者当前字符匹配成功（即S[i] == P[j]），都令i++，j++”，得到i = 1，j = 0，即P[0]继续跟S[1]匹配。</li></ul></li><li>P[0]跟S[1]又失配，j再次等于-1，i、j继续自增，从而P[0]跟S[2]匹配。</li><li>P[0]跟S[2]失配后，P[0]又跟S[3]匹配。</li><li>P[0]跟S[3]再失配，直到P[0]跟S[4]匹配成功，开始执行此条指令的后半段：“如果j = -1，或者当前字符匹配成功（即S[i] == P[j]），都令i++，j++”。</li></ul></li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140726213602848" alt="img"></p></blockquote><ul><li>\2. P[1]跟S[5]匹配成功，P[2]跟S[6]也匹配成功, …，直到当匹配到P[6]处的字符D时失配（即S[10] != P[6]），由于P[6]处的D对应的next 值为2，所以下一步用P[2]处的字符C继续跟S[10]匹配，相当于向右移动：j - next[j] = 6 - 2 =4 位。</li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223809617" alt="img"></p></blockquote><ul><li><em>3</em>. 向右移动4位后，P[2]处的C再次失配，由于C对应的next值为0，所以下一步用P[0]处的字符继续跟S[10]匹配，相当于向右移动：j - next[j] = 2 - 0 = 2 位。</li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223539765" alt="img"></p></blockquote><ul><li><em>4</em>. 移动两位之后，A 跟空格不匹配，模式串后移1 位。</li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223823548" alt="img"></p></blockquote><ul><li><em>5</em>. P[6]处的D再次失配，因为P[6]对应的next值为2，故下一步用P[2]继续跟文本串匹配，相当于模式串向右移动 j - next[j] = 6 - 2 = 4 位。</li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223558140" alt="img"></p></blockquote><ul><li><em>6</em>. 匹配成功，过程结束。</li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140721223611515" alt="img"></p></blockquote><p>  匹配过程一模一样。也从侧面佐证了，next 数组确实是只要将各个最大前缀后缀的公共元素的长度值右移一位，且把初值赋为-1 即可。</p><h4 id="3-3-6-基于《最大长度表》与基于《next-数组》等价"><a href="#3-3-6-基于《最大长度表》与基于《next-数组》等价" class="headerlink" title="3.3.6 基于《最大长度表》与基于《next 数组》等价"></a>3.3.6 基于《最大长度表》与基于《next 数组》等价</h4><p>  我们已经知道，利用next 数组进行匹配失配时，模式串向右移动 j - next [ j ] 位，等价于已匹配字符数 - 失配字符的上一位字符所对应的最大长度值。原因是：</p><ol><li>j 从0开始计数，那么当数到失配字符时，j 的数值就是已匹配的字符数；</li><li>由于next 数组是由最大长度值表整体向右移动一位（且初值赋为-1）得到的，那么失配字符的上一位字符所对应的最大长度值，即为当前失配字符的next 值。</li></ol><p>  但为何本文不直接利用next 数组进行匹配呢？因为next 数组不好求，而一个字符串的前缀后缀的公共元素的最大长度值很容易求。例如若给定模式串“ababa”，要你快速口算出其next 数组，乍一看，每次求对应字符的next值时，还得把该字符排除之外，然后看该字符之前的字符串中有最大长度为多大的相同前缀后缀，此过程不够直接。而如果让你求其前缀后缀公共元素的最大长度，则很容易直接得出结果：0 0 1 2 3，如下表格所示：</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140725232020608" alt="img"></p></blockquote><p>  然后这5个数字 全部整体右移一位，且初值赋为-1，即得到其next 数组：-1 0 0 1 2。</p><h4 id="3-3-7-Next-数组与有限状态自动机"><a href="#3-3-7-Next-数组与有限状态自动机" class="headerlink" title="3.3.7 Next 数组与有限状态自动机"></a>3.3.7 Next 数组与有限状态自动机</h4><p>  next 负责把模式串向前移动，且当第j位不匹配的时候，用第next[j]位和主串匹配，就像打了张“表”。此外，next 也可以看作有限状态自动机的状态，在已经读了多少字符的情况下，失配后，前面读的若干个字符是有用的。</p><p><img src= "/img/loading.gif" data-lazy-src="20140805003320486" alt="img"></p><h4 id="3-3-8-Next-数组的优化"><a href="#3-3-8-Next-数组的优化" class="headerlink" title="3.3.8 Next 数组的优化"></a>3.3.8 Next 数组的优化</h4><p>  行文至此，咱们全面了解了暴力匹配的思路、KMP算法的原理、流程、流程之间的内在逻辑联系，以及next 数组的简单求解（《最大长度表》整体右移一位，然后初值赋为-1）和代码求解，最后基于《next 数组》的匹配，看似洋洋洒洒，清晰透彻，但以上忽略了一个小问题。</p><p>  比如，如果用之前的next 数组方法求模式串“abab”的next 数组，可得其next 数组为-1 0 0 1（0 0 1 2整体右移一位，初值赋为-1），当它跟下图中的文本串去匹配的时候，发现b跟c失配，于是模式串右移j - next[j] = 3 - 1 =2位。</p><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="aHR0cDovL2hpLmNzZG4ubmV0L2F0dGFjaG1lbnQvMjAxMTA2LzE0LzgzOTQzMjNfMTMwODA3NTg1OVpmdWUuanBn" alt="img"></p></blockquote></blockquote><p>  右移2位后，b又跟c失配。事实上，因为在上一步的匹配中，已经得知p[3] = b，与s[3] = c失配，而右移两位之后，让p[ next[3] ] = p[1] = b 再跟s[3]匹配时，必然失配。问题出在哪呢？</p><blockquote><blockquote><p>  <img src= "/img/loading.gif" data-lazy-src="aHR0cDovL2hpLmNzZG4ubmV0L2F0dGFjaG1lbnQvMjAxMTA2LzE0LzgzOTQzMjNfMTMwODA3NTg1OTFreVYuanBn" alt="img"></p></blockquote></blockquote><p>  问题出在不该出现p[j] = p[ next[j] ]。为什么呢？理由是：当p[j] != s[i] 时，下次匹配必然是p[ next [j]] 跟s[i]匹配，如果p[j] = p[ next[j] ]，必然导致后一步匹配失败（因为p[j]已经跟s[i]失配，然后你还用跟p[j]等同的值p[next[j]]去跟s[i]匹配，很显然，必然失配），所以不能允许p[j] = p[ next[j ]]。如果出现了p[j] = p[ next[j] ]咋办呢？如果出现了，则需要再次递归，即令next[j] = next[ next[j] ]。</p><p>  所以，咱们得修改下求next 数组的代码。</p><p>**<br>**</p><ol><li>//优化过后的next 数组求法 </li><li><strong>void GetNextval(char* p, int next[])</strong> </li><li>{ </li><li>  int pLen = strlen(p); </li><li>  next[0] = -1; </li><li>  int k = -1; </li><li>  int j = 0; </li><li>  <strong>while (j &lt; pLen - 1)</strong> </li><li>  { </li><li>​    //p[k]表示前缀，p[j]表示后缀  </li><li>​    <strong>if (k == -1 || p[j] == p[k])</strong> </li><li>​    { </li><li>​      ++j; </li><li>​      ++k; </li><li>​      //较之前next数组求法，改动在下面4行 </li><li>​      <strong>if (p[j] != p[k])</strong> </li><li>​        next[j] = k;  //之前只有这一行 </li><li>​      <strong>else</strong> </li><li>​        //因为不能出现p[j] = p[ next[j ]]，所以当出现时需要继续递归，k = next[k] = next[next[k]] </li><li>​        next[j] = next[k]; </li><li>​    } </li><li>​    <strong>else</strong> </li><li>​    { </li><li>​      k = next[k]; </li><li>​    } </li><li>  } </li><li>} </li></ol><p>  利用优化过后的next 数组求法，可知模式串“abab”的新next数组为：-1 0 -1 0。可能有些读者会问：原始next 数组是前缀后缀最长公共元素长度值右移一位， 然后初值赋为-1而得，那么优化后的next 数组如何快速心算出呢？实际上，只要求出了原始next 数组，便可以根据原始next 数组快速求出优化后的next 数组。还是以abab为例，如下表格所示：</p><p>  <img src= "/img/loading.gif" data-lazy-src="20140801160510832" alt="img"></p><p>只要出现了p[next[j]] = p[j]的情况，则把next[j]的值再次递归。例如在求模式串“abab”的第2个a的next值时，如果是未优化的next值的话，第2个a对应的next值为0，相当于第2个a失配时，下一步匹配模式串会用p[0]处的a再次跟文本串匹配，必然失配。所以求第2个a的next值时，需要再次递归：next[2] = next[ next[2] ] = next[0] = -1（此后，根据优化后的新next值可知，第2个a失配时，执行“如果j = -1，或者当前字符匹配成功（即S[i] == P[j]），都令i++，j++，继续匹配下一个字符”），同理，第2个b对应的next值为0。</p><p>对于优化后的next数组可以发现一点：如果模式串的后缀跟前缀相同，那么它们的next值也是相同的，例如模式串abcabc，它的前缀后缀都是abc，其优化后的next数组为：-1 0 0 -1 0 0，前缀后缀abc的next值都为-1 0 0。</p><p>  然后引用下之前3.1节的KMP代码：</p><p>**<br>**</p><ol><li>int KmpSearch(char* s, char* p) </li><li>{ </li><li>  int i = 0; </li><li>  int j = 0; </li><li>  int sLen = strlen(s); </li><li>  int pLen = strlen(p); </li><li>  <strong>while (i &lt; sLen &amp;&amp; j &lt; pLen)</strong> </li><li>  { </li><li>​    //①如果j = -1，或者当前字符匹配成功（即S[i] == P[j]），都令i++，j++   </li><li>​    <strong>if (j == -1 || s[i] == p[j])</strong> </li><li>​    { </li><li>​      i++; </li><li>​      j++; </li><li>​    } </li><li>​    <strong>else</strong> </li><li>​    { </li><li>​      //②如果j != -1，且当前字符匹配失败（即S[i] != P[j]），则令 i 不变，j = next[j]   </li><li>​      //next[j]即为j所对应的next值    </li><li>​      j = next[j]; </li><li>​    } </li><li>  } </li><li>  <strong>if (j == pLen)</strong> </li><li>​    <strong>return i - j;</strong> </li><li>  <strong>else</strong> </li><li>​    <strong>return -1;</strong> </li><li>} </li></ol><p>  接下来，咱们继续拿之前的例子说明，整个匹配过程如下：</p><p>  <em>1</em>. S[3]与P[3]匹配失败。</p><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="aHR0cDovL2hpLmNzZG4ubmV0L2F0dGFjaG1lbnQvMjAxMTA2LzE0LzgzOTQzMjNfMTMwODA3NTg1NzE0bFcuanBn" alt="img"></p></blockquote></blockquote><p>  <em>2</em>. S[3]保持不变，P的下一个匹配位置是P[next[3]]，而next[3]=0，所以P[next[3]]=P[0]与S[3]匹配。</p><blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="aHR0cDovL2hpLmNzZG4ubmV0L2F0dGFjaG1lbnQvMjAxMTA2LzE0LzgzOTQzMjNfMTMwODA3NTg1NzEzOTAuanBn" alt="img"></p></blockquote></blockquote><p>  <em>3</em>. 由于上一步骤中P[0]与S[3]还是不匹配。此时i=3，j=next [0]=-1，由于满足条件j==-1，所以执行“++i, ++j”，即主串指针下移一个位置，P[0]与S[4]开始匹配。最后j==pLen，跳出循环，输出结果i - j = 4（即模式串第一次在文本串中出现的位置），匹配成功，算法结束。</p><blockquote><blockquote><p>  <img src= "/img/loading.gif" data-lazy-src="aHR0cDovL2hpLmNzZG4ubmV0L2F0dGFjaG1lbnQvMjAxMTA2LzE0LzgzOTQzMjNfMTMwODA3NTg1N2U0MHUuanBn" alt="img"></p></blockquote></blockquote><h3 id="3-4-KMP的时间复杂度分析"><a href="#3-4-KMP的时间复杂度分析" class="headerlink" title="3.4 KMP的时间复杂度分析"></a>3.4 KMP的时间复杂度分析</h3><p>  相信大部分读者读完上文之后，已经发觉其实理解KMP非常容易，无非是循序渐进把握好下面几点：</p><ol><li>如果模式串中存在相同前缀和后缀，即pj-k pj-k+1, …, pj-1 = p0 p1, …, pk-1，那么在pj跟si失配后，让模式串的前缀p0 p1…pk-1对应着文本串si-k si-k+1…si-1，而后让pk跟si继续匹配。</li><li>之前本应是pj跟si匹配，结果失配了，失配后，令pk跟si匹配，相当于j 变成了k，模式串向右移动j - k位。</li><li>因为k 的值是可变的，所以我们用next[j]表示j处字符失配后，下一次匹配模式串应该跳到的位置。换言之，失配前是j，pj跟si失配时，用p[ next[j] ]继续跟si匹配，相当于j变成了next[j]，所以，j = next[j]，等价于把模式串向右移动j - next [j] 位。</li><li>而next[j]应该等于多少呢？next[j]的值由j 之前的模式串子串中有多大长度的相同前缀后缀所决定，如果j 之前的模式串子串中（不含j）有最大长度为k的相同前缀后缀，那么next [j] = k。</li></ol><p>  如之前的图所示：</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140812223633281" alt="img"></p></blockquote><p>  接下来，咱们来分析下KMP的时间复杂度。分析之前，先来回顾下KMP匹配算法的流程：</p><p>“KMP的算法流程：</p><ul><li><p>假设现在文本串S匹配到 i 位置，模式串P匹配到 j 位置</p><ul><li>如果j = -1，或者当前字符匹配成功（即S[i] == P[j]），都令i++，j++，继续匹配下一个字符；</li><li>如果j != -1，且当前字符匹配失败（即S[i] != P[j]），则令 i 不变，j = next[j]。此举意味着失配时，模式串P相对于文本串S向右移动了j - next [j] 位。”</li></ul><p>我们发现如果某个字符匹配成功，模式串首字符的位置保持不动，仅仅是i++、j++；如果匹配失配，i 不变（即 i 不回溯），模式串会跳过匹配过的next [j]个字符。整个算法最坏的情况是，当模式串首字符位于i - j的位置时才匹配成功，算法结束。<br>所以，如果文本串的长度为n，模式串的长度为m，那么匹配过程的时间复杂度为O(n)，算上计算next的O(m)时间，KMP的整体时间复杂度为O(m + n)。</p></li></ul><h2 id="4-扩展1：BM算法"><a href="#4-扩展1：BM算法" class="headerlink" title="4. 扩展1：BM算法"></a>4. 扩展1：BM算法</h2><p>  KMP的匹配是从模式串的开头开始匹配的，而1977年，德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹配算法：Boyer-Moore算法，简称BM算法。该算法从模式串的尾部开始匹配，且拥有在最坏情况下O(N)的时间复杂度。在实践中，比KMP算法的实际效能高。</p><p>  BM算法定义了两个规则：</p><ul><li><p>坏字符规则：当文本串中的某个字符跟模式串的某个字符不匹配时，我们称文本串中的这个失配字符为坏字符，此时模式串需要向右移动，移动的位数 = 坏字符在模式串中的位置 - 坏字符在模式串中最右出现的位置。此外，如果”坏字符”不包含在模式串之中，则最右出现位置为-1。</p></li><li><p>好后缀规则：当字符失配时，后移位数 = 好后缀在模式串中的位置 - 好后缀在模式串上一次出现的位置，且如果好后缀在模式串中没有再次出现，则为-1。</p><p>下面举例说明BM算法。例如，给定文本串“HERE IS A SIMPLE EXAMPLE”，和模式串“EXAMPLE”，现要查找模式串是否在文本串中，如果存在，返回模式串在文本串中的位置。</p><p><em>1</em>. 首先，”文本串”与”模式串”头部对齐，从尾部开始比较。”S”与”E”不匹配。这时，”S”就被称为”坏字符”（bad character），即不匹配的字符，它对应着模式串的第6位。且”S”不包含在模式串”EXAMPLE”之中（相当于最右出现位置是-1），这意味着可以把模式串后移6-(-1)=7位，从而直接移到”S”的后一位。</p></li></ul><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140728192101322" alt="img"></p></blockquote><p>  <em>2</em>. 依然从尾部开始比较，发现”P”与”E”不匹配，所以”P”是”坏字符”。但是，”P”包含在模式串”EXAMPLE”之中。因为“P”这个“坏字符”对应着模式串的第6位（从0开始编号），且在模式串中的最右出现位置为4，所以，将模式串后移6-4=2位，两个”P”对齐。</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140728192109185" alt="img"></p></blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140728192118623" alt="img"></p></blockquote><p>  <em>3</em>. 依次比较，得到 “MPLE”匹配，称为”好后缀”（good suffix），即所有尾部匹配的字符串。注意，”MPLE”、”PLE”、”LE”、”E”都是好后缀。</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140728193254930" alt="img"></p></blockquote><p>  <em>4</em>. 发现“I”与“A”不匹配：“I”是坏字符。如果是根据坏字符规则，此时模式串应该后移2-(-1)=3位。问题是，有没有更优的移法？</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140728193420403" alt="img"></p></blockquote><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140728193428671" alt="img"></p></blockquote><p>  <em>5</em>. 更优的移法是利用好后缀规则：当字符失配时，后移位数 = 好后缀在模式串中的位置 - 好后缀在模式串中上一次出现的位置，且如果好后缀在模式串中没有再次出现，则为-1。<br>  所有的“好后缀”（MPLE、PLE、LE、E）之中，只有“E”在“EXAMPLE”的头部出现，所以后移6-0=6位。<br>  可以看出，“坏字符规则”只能移3位，“好后缀规则”可以移6位。每次后移这两个规则之中的较大值。这两个规则的移动位数，只与模式串有关，与原文本串无关。</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140728194226031" alt="img"></p></blockquote><p>  <em>6</em>. 继续从尾部开始比较，“P”与“E”不匹配，因此“P”是“坏字符”，根据“坏字符规则”，后移 6 - 4 = 2位。因为是最后一位就失配，尚未获得好后缀。</p><blockquote><p><img src= "/img/loading.gif" data-lazy-src="20140728194006343" alt="img"></p></blockquote><p>  由上可知，BM算法不仅效率高，而且构思巧妙，容易理解。</p><h2 id="5-扩展2：Sunday算法"><a href="#5-扩展2：Sunday算法" class="headerlink" title="5. 扩展2：Sunday算法"></a>5. 扩展2：Sunday算法</h2><p>  上文中，我们已经介绍了KMP算法和BM算法，这两个算法在最坏情况下均具有线性的查找时间。但实际上，KMP算法并不比最简单的c库函数strstr()快多少，而BM算法虽然通常比KMP算法快，但BM算法也还不是现有字符串查找算法中最快的算法，本文最后再介绍一种比BM算法更快的查找算法即Sunday算法。</p><p>  Sunday算法由Daniel M.Sunday在1990年提出，它的思想跟BM算法很相似：</p><ul><li><p>只不过Sunday算法是从前往后匹配，在匹配失败时关注的是文本串中参加匹配的最末位字符的下一位字符。</p><ul><li>如果该字符没有在模式串中出现则直接跳过，即移动位数 = 匹配串长度 + 1；</li><li>否则，其移动位数 = 模式串中最右端的该字符到末尾的距离+1。</li></ul><p>下面举个例子说明下Sunday算法。假定现在要在文本串”substring searching algorithm”中查找模式串”search”。</p><p><em>1</em>. 刚开始时，把模式串与文本串左边对齐：<br>substring searching algorithm<br>search<br>^<br><em>2</em>. 结果发现在第2个字符处发现不匹配，不匹配时关注文本串中参加匹配的最末位字符的下一位字符，即标粗的字符 i，因为模式串search中并不存在i，所以模式串直接跳过一大片，向右移动位数 = 匹配串长度 + 1 = 6 + 1 = 7，从 i 之后的那个字符（即字符n）开始下一步的匹配，如下图：</p></li></ul><p>substring searching algorithm<br>　　　 search<br>　　　　^<br>  <em>3</em>. 结果第一个字符就不匹配，再看文本串中参加匹配的最末位字符的下一位字符，是’r’，它出现在模式串中的倒数第3位，于是把模式串向右移动3位（r 到模式串末尾的距离 + 1 = 2 + 1 =3），使两个’r’对齐，如下：<br>substring searching algorithm<br>　　　　 search<br>　　　　　　　^</p><p>  <em>4</em>. 匹配成功。</p><p>  回顾整个过程，我们只移动了两次模式串就找到了匹配位置，缘于Sunday算法每一步的移动量都比较大，效率很高。完。</p><h2 id="6-参考文献"><a href="#6-参考文献" class="headerlink" title="6. 参考文献"></a>6. 参考文献</h2><ol><li>《算法导论》的第十二章：字符串匹配；</li><li>本文中模式串“ABCDABD”的部分图来自于此文：<a href="http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html">http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html</a>；</li><li>本文3.3.7节中有限状态自动机的图由微博网友@龚陆安 绘制：<a href="http://d.pr/i/NEiz%EF%BC%9B">http://d.pr/i/NEiz；</a></li><li>北京7月暑假班邹博半小时KMP视频：<a href="http://www.julyedu.com/video/play/id/5%EF%BC%9B">http://www.julyedu.com/video/play/id/5；</a></li><li>北京7月暑假班邹博第二次课的PPT：<a href="http://yun.baidu.com/s/1mgFmw7u%EF%BC%9B">http://yun.baidu.com/s/1mgFmw7u；</a></li><li>理解KMP 的9张PPT：<a href="http://weibo.com/1580904460/BeCCYrKz3#_rnd1405957424876%EF%BC%9B">http://weibo.com/1580904460/BeCCYrKz3#_rnd1405957424876；</a></li><li>详解KMP算法（多图）：<a href="http://www.cnblogs.com/yjiyjige/p/3263858.html%EF%BC%9B">http://www.cnblogs.com/yjiyjige/p/3263858.html；</a></li><li>本文第4部分的BM算法参考自此文：<a href="http://www.ruanyifeng.com/blog/2013/05/boyer-moore_string_search_algorithm.html%EF%BC%9B">http://www.ruanyifeng.com/blog/2013/05/boyer-moore_string_search_algorithm.html；</a></li><li><a href="http://youlvconglin.blog.163.com/blog/static/5232042010530101020857/">http://youlvconglin.blog.163.com/blog/static/5232042010530101020857</a>；</li><li>《数据结构 第二版》，严蔚敏 &amp; 吴伟民编著；</li><li><a href="http://blog.csdn.net/v_JULY_v/article/details/6545192%EF%BC%9B">http://blog.csdn.net/v_JULY_v/article/details/6545192；</a></li><li><a href="http://blog.csdn.net/v_JULY_v/article/details/6111565%EF%BC%9B">http://blog.csdn.net/v_JULY_v/article/details/6111565；</a></li><li>Sunday算法的原理与实现：<a href="http://blog.chinaunix.net/uid-22237530-id-1781825.html%EF%BC%9B">http://blog.chinaunix.net/uid-22237530-id-1781825.html；</a></li><li>模式匹配之Sunday算法：<a href="http://blog.csdn.net/sunnianzhong/article/details/8820123%EF%BC%9B">http://blog.csdn.net/sunnianzhong/article/details/8820123；</a></li><li>一篇KMP的英文介绍：<a href="http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm%EF%BC%9B">http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm；</a></li><li>我2014年9月3日在西安电子科技大学的面试&amp;算法讲座视频（第36分钟~第94分钟讲KMP）：<a href="http://www.julyedu.com/video/play/21%E3%80%82">http://www.julyedu.com/video/play/21。</a></li><li>一幅图理解KMP next数组的求法：<a href="http://v.atob.site/kmp-next.html">http://v.atob.site/kmp-next.html </a>。</li></ol><h2 id="7-后记"><a href="#7-后记" class="headerlink" title="7. 后记"></a>7. 后记</h2><p>  对之前混乱的文章给广大读者带来的困扰表示致歉，对重新写就后的本文即将给读者带来的清晰表示欣慰。希望大部分的初学者，甚至少部分的非计算机专业读者也能看懂此文。有任何问题，欢迎随时批评指正，thanks。</p><p>  July、二零一四年八月二十二日晚九点。</p><p>本文作者：ZzUuOo666</p><p>本文链接：<a href="https://www.cnblogs.com/zzuuoo666/p/9028287.html">https://www.cnblogs.com/zzuuoo666/p/9028287.html</a></p><p>版权声明：本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆<a href="https://www.cnblogs.com/zzuuoo666/p/9028287.html">许可协议</a>进行许可。</p>]]></content>
      
      
      
        <tags>
            
            <tag> algorithm </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>普里姆算法介绍</title>
      <link href="unclass/prim/"/>
      <url>unclass/prim/</url>
      
        <content type="html"><![CDATA[<p>普里姆(Prim)算法，和克鲁斯卡尔算法一样，是用来求加权连通图的最小生成树的算法。</p><p><strong>基本思想</strong><br>对于图G而言，V是所有顶点的集合；现在，设置两个新的集合U和T，其中U用于存放G的最小生成树中的顶点，T存放G的最小生成树中的边。 从所有uЄU，vЄ(V-U) (V-U表示出去U的所有顶点)的边中选取权值最小的边(u, v)，将顶点v加入集合U中，将边(u, v)加入集合T中，如此不断重复，直到U=V为止，最小生成树构造完毕，这时集合T中包含了最小生成树中的所有边。</p><h3 id="普里姆算法图解"><a href="#普里姆算法图解" class="headerlink" title="普里姆算法图解"></a><strong>普里姆算法图解</strong></h3><p><a href="https://github.com/wangkuiwu/datastructs_and_algorithm/blob/master/pictures/graph/01.jpg?raw=true"><img src= "/img/loading.gif" data-lazy-src="https://github.com/wangkuiwu/datastructs_and_algorithm/blob/master/pictures/graph/01.jpg?raw=true" alt="img"></a></p><p>以上图G4为例，来对普里姆进行演示(从第一个顶点A开始通过普里姆算法生成最小生成树)。</p><p><a href="https://github.com/wangkuiwu/datastructs_and_algorithm/blob/master/pictures/graph/02.jpg?raw=true"><img src= "/img/loading.gif" data-lazy-src="https://github.com/wangkuiwu/datastructs_and_algorithm/blob/master/pictures/graph/02.jpg?raw=true" alt="img"></a></p><p><strong>初始状态</strong>：V是所有顶点的集合，即V={A,B,C,D,E,F,G}；U和T都是空！<br><strong>第1步</strong>：将顶点A加入到U中。<br>  此时，U={A}。<br><strong>第2步</strong>：将顶点B加入到U中。<br>  上一步操作之后，U={A}, V-U={B,C,D,E,F,G}；因此，边(A,B)的权值最小。将顶点B添加到U中；此时，U={A,B}。<br><strong>第3步</strong>：将顶点F加入到U中。<br>  上一步操作之后，U={A,B}, V-U={C,D,E,F,G}；因此，边(B,F)的权值最小。将顶点F添加到U中；此时，U={A,B,F}。<br><strong>第4步</strong>：将顶点E加入到U中。<br>  上一步操作之后，U={A,B,F}, V-U={C,D,E,G}；因此，边(F,E)的权值最小。将顶点E添加到U中；此时，U={A,B,F,E}。<br><strong>第5步</strong>：将顶点D加入到U中。<br>  上一步操作之后，U={A,B,F,E}, V-U={C,D,G}；因此，边(E,D)的权值最小。将顶点D添加到U中；此时，U={A,B,F,E,D}。<br><strong>第6步</strong>：将顶点C加入到U中。<br>  上一步操作之后，U={A,B,F,E,D}, V-U={C,G}；因此，边(D,C)的权值最小。将顶点C添加到U中；此时，U={A,B,F,E,D,C}。<br><strong>第7步</strong>：将顶点G加入到U中。<br>  上一步操作之后，U={A,B,F,E,D,C}, V-U={G}；因此，边(E,G)的权值最小。将顶点G添加到U中；此时，U=V。</p><p>此时，最小生成树构造完成！它包括的顶点依次是：<strong>A B F E D C G</strong>。</p><h3 id="普里姆算法的代码说明"><a href="#普里姆算法的代码说明" class="headerlink" title="普里姆算法的代码说明"></a><strong>普里姆算法的代码说明</strong></h3><p>以”邻接矩阵”为例对普里姆算法进行说明，对于”邻接表”实现的图在后面会给出相应的源码。</p><p><strong>1. 基本定义</strong></p><p><a href="javascript:void(0);"><img src= "/img/loading.gif" data-lazy-src="copycode.gif" alt="复制代码"></a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 邻接矩阵</span><br><span class="line">typedef struct _graph</span><br><span class="line">&#123;</span><br><span class="line">    char vexs[MAX];       &#x2F;&#x2F; 顶点集合</span><br><span class="line">    int vexnum;           &#x2F;&#x2F; 顶点数</span><br><span class="line">    int edgnum;           &#x2F;&#x2F; 边数</span><br><span class="line">    int matrix[MAX][MAX]; &#x2F;&#x2F; 邻接矩阵</span><br><span class="line">&#125;Graph, *PGraph;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 边的结构体</span><br><span class="line">typedef struct _EdgeData</span><br><span class="line">&#123;</span><br><span class="line">    char start; &#x2F;&#x2F; 边的起点</span><br><span class="line">    char end;   &#x2F;&#x2F; 边的终点</span><br><span class="line">    int weight; &#x2F;&#x2F; 边的权重</span><br><span class="line">&#125;EData;</span><br></pre></td></tr></table></figure><p><a href="javascript:void(0);"><img src= "/img/loading.gif" data-lazy-src="copycode.gif" alt="复制代码"></a></p><p>Graph是邻接矩阵对应的结构体。<br>vexs用于保存顶点，vexnum是顶点数，edgnum是边数；matrix则是用于保存矩阵信息的二维数组。例如，matrix[i][j]=1，则表示”顶点i(即vexs[i])”和”顶点j(即vexs[j])”是邻接点；matrix[i][j]=0，则表示它们不是邻接点。<br>EData是邻接矩阵边对应的结构体。</p><p><strong>2. 普里姆算法</strong></p><p><a href="javascript:void(0);"><img src= "/img/loading.gif" data-lazy-src="copycode.gif" alt="复制代码"></a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br></pre></td><td class="code"><pre><span class="line">#include&lt;stdio.h&gt;</span><br><span class="line">#include&lt;stdlib.h&gt;</span><br><span class="line">#include&lt;malloc.h&gt;</span><br><span class="line">#include&lt;string.h&gt;</span><br><span class="line">#define MAX 100</span><br><span class="line">#define INF (~(0x1&lt;&lt;31))</span><br><span class="line">typedef struct Graph</span><br><span class="line">&#123;</span><br><span class="line">    char vexs[MAX];</span><br><span class="line">    int vexnum;</span><br><span class="line">    int edgnum;</span><br><span class="line">    int matrix[MAX][MAX];</span><br><span class="line">&#125; Graph,*PGraph;</span><br><span class="line"></span><br><span class="line">typedef struct EdgeData</span><br><span class="line">&#123;</span><br><span class="line">    char start;</span><br><span class="line">    char end;</span><br><span class="line">    int weight;</span><br><span class="line">&#125; EData;</span><br><span class="line"></span><br><span class="line">static int get_position(Graph g,char ch)</span><br><span class="line">&#123;</span><br><span class="line">    int i;</span><br><span class="line">    for(i&#x3D;0; i&lt;g.vexnum; i++)</span><br><span class="line">        if(g.vexs[i]&#x3D;&#x3D;ch)</span><br><span class="line">            return i;</span><br><span class="line">    return -1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Graph* create_graph()</span><br><span class="line">&#123;</span><br><span class="line">    char vexs[]&#x3D; &#123;&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;,&#39;G&#39;&#125;;</span><br><span class="line">    int matrix[][7]&#x3D;</span><br><span class="line">    &#123;</span><br><span class="line">        &#123;0,12,INF,INF,INF,16,14&#125;,</span><br><span class="line">        &#123;12,0,10,INF,INF,7,INF&#125;,</span><br><span class="line">        &#123;INF,10,0,3,5,6,INF&#125;,</span><br><span class="line">        &#123;INF,INF,3,0,4,INF,INF&#125;,</span><br><span class="line">        &#123;INF,INF,5,4,0,INF,8&#125;,</span><br><span class="line">        &#123;16,7,6,INF,2,0,9&#125;,</span><br><span class="line">        &#123;14,INF,INF,INF,8,9,0&#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    int vlen&#x3D;sizeof(vexs)&#x2F;sizeof(vexs[0]);</span><br><span class="line">    int i,j;</span><br><span class="line">    Graph *pG;</span><br><span class="line">    if((pG&#x3D;(Graph*)malloc(sizeof(Graph)))&#x3D;&#x3D;NULL)</span><br><span class="line">        return NULL;</span><br><span class="line">    memset(pG,0,sizeof(pG));</span><br><span class="line">    pG-&gt;vexnum&#x3D;vlen;</span><br><span class="line">    for(i&#x3D;0; i&lt;pG-&gt;vexnum; i++)</span><br><span class="line">        pG-&gt;vexs[i]&#x3D;vexs[i];</span><br><span class="line">    for(i&#x3D;0; i&lt;pG-&gt;vexnum; i++)</span><br><span class="line">        for(j&#x3D;0; j&lt;pG-&gt;vexnum; j++)</span><br><span class="line">            pG-&gt;matrix[i][j]&#x3D;matrix[i][j];</span><br><span class="line">    for(i&#x3D;0; i&lt;pG-&gt;vexnum; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        for(j&#x3D;0; j&lt;pG-&gt;vexnum; j++)</span><br><span class="line">        &#123;</span><br><span class="line">            if(i!&#x3D;j&amp;&amp;pG-&gt;matrix[i][j]!&#x3D;INF)</span><br><span class="line">                pG-&gt;edgnum++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    pG-&gt;edgnum&#x2F;&#x3D;2;</span><br><span class="line">    return pG;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">void print_graph(Graph G)</span><br><span class="line">&#123;</span><br><span class="line">    int i,j;</span><br><span class="line">    printf(&quot;Matrix Graph: \n&quot;);</span><br><span class="line">    for(i&#x3D;0; i&lt;G.vexnum; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        for(j&#x3D;0; j&lt;G.vexnum; j++)</span><br><span class="line">            printf(&quot;%10d &quot;,G.matrix[i][j]);</span><br><span class="line">        printf(&quot;\n&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">EData* get_edges(Graph G)</span><br><span class="line">&#123;</span><br><span class="line">    EData *edges;</span><br><span class="line">    edges&#x3D;(EData*)malloc(G.edgnum*sizeof(EData));</span><br><span class="line">    int i,j;</span><br><span class="line">    int index&#x3D;0;</span><br><span class="line">    for(i&#x3D;0; i&lt;G.vexnum; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        for(j&#x3D;i+1; j&lt;G.vexnum; j++)</span><br><span class="line">        &#123;</span><br><span class="line">            if(G.matrix[i][j]!&#x3D;INF)</span><br><span class="line">            &#123;</span><br><span class="line">                edges[index].start&#x3D;G.vexs[i];</span><br><span class="line">                edges[index].end&#x3D;G.vexs[j];</span><br><span class="line">                edges[index].weight&#x3D;G.matrix[i][j];</span><br><span class="line">                index++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return edges;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">void prim(Graph G,int start)</span><br><span class="line">&#123;</span><br><span class="line">    int min,i,j,k,m,n,sum;</span><br><span class="line">    int index&#x3D;0;</span><br><span class="line">    char prim[MAX];</span><br><span class="line">    int weight[MAX];</span><br><span class="line"></span><br><span class="line">    prim[index++]&#x3D;G.vexs[start];</span><br><span class="line"></span><br><span class="line">    for(i&#x3D;0; i&lt;G.vexnum; i++)</span><br><span class="line">        weight[i]&#x3D;G.matrix[start][i];</span><br><span class="line">    weight[start]&#x3D;0;</span><br><span class="line"></span><br><span class="line">    for(i&#x3D;0; i&lt;G.vexnum; i++)</span><br><span class="line">    &#123;</span><br><span class="line">       &#x2F;&#x2F;i用来控制循环的次数，每次加入一个结点，但是因为start已经加入，所以当i为start是跳过</span><br><span class="line">        if(start&#x3D;&#x3D;i)</span><br><span class="line">            continue;</span><br><span class="line">        j&#x3D;0;</span><br><span class="line">        k&#x3D;0;</span><br><span class="line">        min&#x3D;INF;</span><br><span class="line">        for(k&#x3D;0; k&lt;G.vexnum; k++)</span><br><span class="line">        &#123;</span><br><span class="line">            if(weight[k]&amp;&amp;weight[k]&lt;min)</span><br><span class="line">            &#123;</span><br><span class="line">                min&#x3D;weight[k];</span><br><span class="line">                j&#x3D;k;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        sum+&#x3D;min;</span><br><span class="line">        prim[index++]&#x3D;G.vexs[j];</span><br><span class="line">        weight[j]&#x3D;0;</span><br><span class="line">        for(k&#x3D;0; k&lt;G.vexnum; k++)</span><br><span class="line">        &#123;</span><br><span class="line">            if(weight[k]&amp;&amp;G.matrix[j][k]&lt;weight[k])</span><br><span class="line">                weight[k]&#x3D;G.matrix[j][k];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    &#x2F;&#x2F; 计算最小生成树的权值</span><br><span class="line">    sum &#x3D; 0;</span><br><span class="line">    for (i &#x3D; 1; i &lt; index; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        min &#x3D; INF;</span><br><span class="line">        &#x2F;&#x2F; 获取prims[i]在G中的位置</span><br><span class="line">        n &#x3D; get_position(G, prim[i]);</span><br><span class="line">        &#x2F;&#x2F; 在vexs[0...i]中，找出到j的权值最小的顶点。</span><br><span class="line">        for (j &#x3D; 0; j &lt; i; j++)</span><br><span class="line">        &#123;</span><br><span class="line">            m &#x3D; get_position(G, prim[j]);</span><br><span class="line">            if (G.matrix[m][n]&lt;min)</span><br><span class="line">                min &#x3D; G.matrix[m][n];</span><br><span class="line">        &#125;</span><br><span class="line">        sum +&#x3D; min;</span><br><span class="line">    &#125;</span><br><span class="line">    printf(&quot;PRIM(%c)&#x3D;%d: &quot;, G.vexs[start], sum);</span><br><span class="line">    for (i &#x3D; 0; i &lt; index; i++)</span><br><span class="line">        printf(&quot;%c &quot;, prim[i]);</span><br><span class="line">    printf(&quot;\n&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">int main()</span><br><span class="line">&#123;</span><br><span class="line">    Graph *pG;</span><br><span class="line">    pG&#x3D;create_graph();</span><br><span class="line">    print_graph(*pG);</span><br><span class="line">    prim(*pG,0);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="javascript:void(0);"><img src= "/img/loading.gif" data-lazy-src="copycode.gif" alt="复制代码"></a></p><p>运行结果：</p><p><img src= "/img/loading.gif" data-lazy-src="052007314983645.png" alt="img"></p><p>分类: <a href="https://www.cnblogs.com/wlzy/category/1017131.html">计算机算法</a></p>]]></content>
      
      
      
        <tags>
            
            <tag> algorithm </tag>
            
        </tags>
      
    </entry>
    
    
  
  
</search>
